السابقالفهرسالتالي

الفصل 3

العمليات

 

3.1 النقطة العائمة

في الفصل السابق واجهنا بعض المشاكل عند التعامل مع الأعداد غير الصحيحة. لقد تفادينا المشكلة بحساب النسبة المئوية بدلاً من الكسر، لكن الحل الأعم هو استعمال الأعداد العشرية، التي تستطيع التعبير عن الكسور كما تعبر عن الأعداد الصحيحة. في لغة Java، تدعى الأعداد العشرية double.

يمكنك إنشاء متغيرات عشرية وإسناد القيم لها باستخدام نفس التعليمات التي استخدمناها للأنواع الأخرى. مثلاً:

double pi;
pi = 3.14159;
كما يمكن أيضاً التصريح عن متغير وإسناد قيمة له في الوقت نفسه:
int x = 1;
String empty = "";
double pi = 3.14159;
في الواقع، هذا الأسلوب شائع جداً. أحياناً ندعو التصريح والإسناد المدمجين بالتهيئة (initialization).

على الرغم من أن الأعداد العشرية مفيدة، فهي غالباً ما تكون مصدراً للارتباك بسبب ظهور ما يشبه التداخل بين الأعداد الصحيحة والأعداد العشرية. مثلاً، إذا كانت لديك القيمة 1، فهل هي عدد صحيح، أم عدد عشري، أم الاثنين معاً؟

إذا تحدثنا بدقة، فإن Java تفرّق بين القيمة الصحيحة 1 وبين القيمة العشرية 1.0، حتى لو بدا أنهما نفس العدد، فهما يختلفان بالنوع، وعلى وجه الدقة، لا يسمح لك بالقيام بعمليات إسناد بين النوعين. مثلاً، ما يلي ليس مسموحاً:

int x = 1.1;
لأن المتغير على اليسار int والقيمة على اليمين double. لكنه من السهل نسيان هذه القاعدة، خاصة بوجود الأماكن التي تقوم فيها Java بالتحويل بين الأنواع تلقائياً. مثلاً:
double y = 1;
من المفترض تقنياً ألا تكون هذه التعليمة مشروعة، لكن Java تسمح بها عن طريق التحويل التلقائي من int إلى double. هذا التساهل مريح، لكن يمكن له أن يسبب المشاكل؛ مثلاً:
double y = 1 / 3;
قد تتوقع أن يعطى المتغير y القيمة 0.333333، وهي قيمة عشرية مشروعة، لكنه في الواقع سيعطى القيمة 0.0. السبب هو أن العبارة على اليمين هي نسبة بين عددين صحيحين، لذا تقوم Java بإجراء قسمة صحيحة، والتي تنتج القيمة الصحيحة 0. ثم يتم تحويلها إلى قيمة عشرية، الناتج هو 0.0.

إحدى الطرق لحل هذه المشكلة (بعد أن تكتشف أن هذه هي المشكلة) هو جعل الطرف الأيمن عبارة عشرية:

double y = 1.0 / 3.0;
هذا سيعطي y القيمة 0.333333، كما هو متوقع. كل العمليات التي شاهدناها حتى الآن – الجمع، الطرح، الضرب، والقسمة – تعمل أيضاً مع القيم العشرية، مع أنك قد تكون مهتماً بمعرفة أن آلية العمل الضمنية مختلفة كلياً. في الواقع، معظم المعالجات تملك عتاداً خاصاً لتنفيذ العمليات العشرية فقط.

3.2 التحويل من double إلى int

كما ذكرت من قبل، Java تحول الأعداد الصحيحة إلى عشرية تلقائياً إذا دعت الحاجة، بسبب عدم فقدان أية معلومات أثناء التحويل. من جهة أخرى، التحويل من double إلى int يتطلب تقريبا. لا تنفذ Java هذه العملية تلقائياً، وذلك لتضمن أنك، بصفتك المبرمج، مدركاً لضياع القسم العشري من العدد.

أبسط طريقة لتحول قيمة عشرية إلى صحيحة هي استعمال قولبة الأنماط (typecast). تم تسمية قولبة الأنماط هكذا لأنها تسمح لك بأخذ قيمة من نوع معين و"قولبتها" في نوع آخر (بمعنى إعادة تشكيلها أو تحويلها).

لسوء الحظ، فإن البنية المستعملة في قولبة الأنماط بشعة: تضع اسم النوع في أقواس وتستعمله كعامل. مثلاً،

int x = (int) Math.PI;
العامل (int) له أثر تحويل ما يليه إلى int، لذا فإن x سيحصل على القيمة 3.

قولبة الأنماط لها أولوية على العمليات الحسابية، ففي المثال التالي، سيتم تحويل قيمة PI إلى قيمة صحيحة أولاً، وسيكون الناتج 60.0 وليس 62.

double x = (int) Math.PI * 20.0;
التحويل إلى قيمة صحيحة دائماً يقرب العدد إلى الأدنى، حتى لو كان الجزء العشري 0.99999999. هاتان الخاصيتان (الأولوية والتقريب) قد تجعلان من قولبة الأنماط سبباً للخطأ.

3.3 التوابع الرياضية

< p> في الرياضيات، شاهدت توابعاً مثل sin وlog على الأغلب، وتعلمت حساب قيمة عبارات مثل sin(π/2) وlog(1/x). أولاً، تحسب قيمة العبارة بين قوسين، التي تدعى متحول (argument) التابع. مثلاً، π/2 تقريباً 1.571، و1/x هو 0.1 (بفرض أن x يساوي 10).

بعد ذلك ستتمكن من حساب قيمة التابع نفسه، إما بالبحث عنه في جدول أو بتنفيذ حسابات متنوعة. إن جيب 1.571 هو 1، و لوغاريتم 0.1 هو -1 (على اعتبار أن log تشير إلى اللوغاريتم ذا الأساس 10).

هذه العملية يمكن تطبيقها بشكل متكرر لحساب عبارات أكثر تعقيداً مثل log(1/sin(π/2)). أولاً نحسب قيمة متغير التابع الداخلي، ثم نحسب قيمة ذلك التابع، ونتابع على هذا المنوال.

توفر Java مجموعة من التوابع تنفذ معظم العمليات الرياضية الشائعة. هذه التوابع تدعى عمليات (methods).

تستدعى العمليات الرياضية باستخدام نحو مشابه لأوامر الطباعة print التي سبق أن شاهدناها:

double root = Math.sqrt(17.0);
double angle = 1.5;
double height = Math.sin(angle);
يعطي المثال الأول المتغير root الجذر التربيعي للعدد 17. يحسب المثال الثاني جيب قيمة المتغير angle، وهي 1.5. تفترض Java أن القيم التي تستخدمها مع sin ومع التوابع المثلثية الأخرى (cos, tan) مقدرة بالراديان. للتحويل من الدرجات إلى الراديان، يمكنك التقسيم على 360 والضرب ب2π. للسهولة، توفر Java قيمة π بصورة جاهزة:
double degrees = 90;
double angle = degrees * 2 * Math.PI / 360.0;
لاحظ أن PI مكتوبة بأحرف كبيرة بالكامل. لن تتعرف Java على Pi، pi أو pie.

من العمليات المفيدة في صنف Math هي round، التي تدور القيم العشرية إلى أقرب قيمة صحيحة وترجع int.

int x = Math.round(Math.PI * 20.0);
في هذه الحالة يتم تنفيذ الضرب أولاً، قبل استدعاء العملية round. الناتج هو 63 (قرِّبت القيمة 62.8319 إلى القيمة الأعلى).

3.4 التركيب

كما في التوابع الرياضية -الحقيقية-، يمكن تركيب (compose) العمليات في Java، بمعنى أنك تستطيع استعمال عبارة ما كجزء من عبارة أخرى. مثلاً، يمكنك استخدام أية عبارة حسابية كمتحول لعملية ما:

double x = Math.cos(angle + Math.PI/2);
هذه التعليمة تأخذ قيمة Math.PI، وتقسمها على اثنين ثم تضيف الناتج إلى قيمة المتغير angle. بعد ذلك يمرر المجموع كمتحول لعملية cos. (لاحظ أن PI هو اسم متغير، وليس عملية، لذلك لا نمرر له أية متحولات، ولا حتى المتحول الفارغ () ).

يمكنك أيضاً أخذ نتيجة إحدى العمليات وتمريرها كمتحول لعملية أخرى:

double x = Math.exp(Math.log (10.0.));
في Java، تابع log يستعمل الأساس e دائماً، لذلك فإن هذه التعليمة تحسب اللوغاريتم ذا الأساس e للعدد 10 ثم ترفع e إلى تلك القوة. ويتم إسناد النتيجة إلى x؛ أتمنى أن تعرف ما هي.

3.5 إضافة عمليات جديدة

حتى الآن كنا نستعمل العمليات المبنية مسبقاً في مكتبات Java، لكن يمكننا أيضاً أن نضيف عمليات جديدة. في الواقع، لقد رأينا سابقاً تعريف إحدى العمليات: main. العملية المسماة main مميزة لأنها تشير إلى مكان بدء تنفيذ البرنامج، لكن البنية المستخدمة في main هي نفس المستخدمة في العمليات الأخرى:

public static void NAME( LIST OF PARAMETERS ) {
    STATEMENTS
}
يمكنك استخدام أي اسم تريده لعمليتك، عدا أنك لا تستطيع تسميتها main أو أي كلمة أخرى محجوزة في Java. اصطلاحاً، تبدأ أسماء العمليات في Java بأحرف صغيرة وتستخدم "حروف الجَمَل – camel caps"، وهو اسم طريف يعني كتابة الحرف الأول من الكلمات المتلاصقة بشكله الكبير، كما نقوم عندما jamWordsTogetherLikeThis.

قائمة المعاملات تحدد ماهية المعلومات، في حال وجودها، التي يتوجب عليك توفيرها حتى تستعمل (أو تستدعي (invoke)) التابع الجديد.

المعامل الوحيد للعملية main هو String[] args، الذي يشير إلى أنه يجب على كل من يستدعي main أن يوفر مصفوفة من السلاسل المحرفية (سنصل إلى المصفوفات في الفصل 10). العمليتان اللتان سنكتبهما في البداية ليس لهما أية معاملات، لذا فإن بنيتها ستبدو مثل هذه:

public static void newLine() {
   System.out.println("");
}
هذه العملية اسمها newLine، والأقواس الفارغة تبين أنها لا تأخذ أية معاملات. وهي تتضمن تعليمة واحدة فقط، تقوم بطباعة سلسلة فارغة (empty String)، أشرنا إليها بالعلامتين "". إن طباعة سلسلة محرفية لا تحوي أية حروف قد يبدو غير مفيد على الإطلاق، إلا إذا تذكرت أن تعليمة println تنقل مؤشر الطباعة إلى السطر التالي بعد الانتهاء من الطباعة، إذن فهذه التعليمة تؤدي إلى تجاوز سطر واحد ونقل مؤشر الطباعة إلى السطر التالي.

داخل main يمكننا استدعاء هذه العملية الجديدة باستعمال طريقة مشابهة للطريقة المستخدمة عند استدعاء أوامر Java الجاهزة:

public static void main(String[] args) {
   System.out.println("First line.");
   newLine();
   System.out.println("Second line.");
}
إن خرج البرنامج هو
First line.

Second line.
لاحظ المسافة الإضافية بين السطرين. ماذا لو أردنا المزيد من المساحة بين السطرين؟ يمكننا استدعاء العملية نفسها عدة مرات:
public static void main(String[] args) {
   System.out.println("First line.");
   newLine();
   newLine();
   newLine();
   System.out.println("Second line.");
}
أو يمكننا كتابة عملية جديدة، اسمها threeLine، تقوم بطباعة ثلاثة أسطر:
public static void threeLine() {
    newLine(); newLine(); newLine();
}

public static void main(String[] args) {
    System.out.println("First line.");
    threeLine();
    System.out.println("Second line.");
}
يجب أن تنتبه لعدة أشياء في هذا البرنامج:

حتى الآن، قد لا يبدو سبب كل هذا العناء في كتابة هذه العمليات الجديدة واضحاً. في الواقع، هناك العديد من الأسباب، لكن هذا المثال يشرح اثنين فقط:

  1. إنشاء عملية جديدة يعطيك القدرة على إعطاء اسم لمجموعة من التعليمات. يمكن للعمليات أن تبسط البرنامج بإخفاء حسابات معقدة وراء أمر واحد، وباستعمال الكلمات الإنكليزية بدلاً من الشفرة الغامضة. أيهما أوضح، newLine أو System.out.println("") ؟
  2. إنشاء عملية جديدة يمكن جعل البرنامج أصغر بالتخلص من الشفرة المكررة. مثلاً، كيف يمكنك طباعة تسعة أسطر جديدة متعاقبة؟ يمكنك استدعاء threeLine ثلاثة مرات. في القسم 7.7 سنعود إلى هذا السؤال وسأسرد المزيد من فوائد تقسيم البرامج إلى عمليات.

3.6 الأصناف والعمليات

بجمع كل أجزاء الشفرة من القسم السابق، سيبدو التعريف الكامل للصنف كالتالي:

class NewLine {

   public static void newLine() {
      System.out.printlin("");
   }

   public static void threeLine() {
      newLine(); newLine(); newLine();
   }

   public static void main (Sttring[] args) {
      System.out.println ("First line.");
      threeLine();
      System.out.println ("Second line.");
   }
}
يبين السطر الأول أن هذا تعريف صنف للصنف الجديد المسمى NewLine. الصنف هو مجموعة من العمليات المترابطة. في هذه الحالة، يحتوي الصنف المسمى NewLine على ثلاث عمليات، اسمها newLine، وthreeLine، وmain.

الصنف الآخر الذي شاهدناه كان الصنف Math. وهو يحتوي على العمليات المسماة sqrt، وsin، وغيرها الكثير. عندما نستدعي تابعاً رياضياً، علينا تحديد اسم الصنف (Math) واسم التابع. لهذا السبب فإن بنية التعليمة المستخدمة لاستدعاء العمليات الجاهزة تختلف قليلاً عن البنية المستخدمة لاستدعاء العمليات التي نكتبها:

Math.pow(2.0, 10.0);
newLine();
التعليمة الأولى تستدعي العملية pow من الصنف Math (التي ترفع المتغير الأول إلى قوة المتغير الثاني). التعليمة الثانية تستدعي العملية newLine، والتي تفترض Java وجودها (وهي موجودة فعلاً) في صنف NewLine، الذي نقوم بكتابته.

إذا حاولنا استدعاء العملية من صنف خاطئ، سيعطي المجمّع خطأ. مثلاً، إذا كتبتَ:

pow(2.0, 10.0);
سيقول المجمع شيئاً مثل، "Can’t find a method named pow in class NewLine." — " لا يمكن العثور على عملية باسم pow في الصنف NewLine". إذا رأيت هذه الرسالة، فلربما تساءلت عن سبب بحثه عن pow في تعريف صنفك. الآن أنت تعرف.

3.7 البرامج ذات العمليات المتعددة

عندما تنظر إلى تعريف صنف يحوي عمليات متعددة، فإن قراءته من الأعلى إلى الأسفل تبدو مغرية، لكن ذلك سيكون مشوشاً على الأغلب، لأنه ليس ترتيب تنفيذ البرنامج (order of execution of the program).

يبدأ التنفيذ دائماً عند التعليمة الأولى من main، بغض النظر عن موقعها من البرنامج (في حالتنا هذه فقد تعمدت وضعها في النهاية). يتم تنفيذ التعليمات واحدة تلو الأخرى، بالترتيب، حتى تصل إلى استدعاء لعملية. استدعاءات العمليات تشبه الانعطافات في مجرى التنفيذ. بدلاً من الذهاب إلى التعليمة التالية، تذهب إلى السطر الأول من العملية المستدعاة، تنفذ جميع التعليمات الموجودة هناك، ثم تعود وتتابع التنفيذ ثانية من المكان الذي انعطفت منه.

هذا يبدو بسيطاً بما يكفي، عدا أنك يجب أن تتذكر أن تلك العملية قادرة على استدعاء عملية أخرى. بالتالي، بينما نحن في وسط main، قد نضطر إلى الذهاب لتنفيذ التعليمات في threeLine. ولكن بينما نحن ننفذ تعليمات threeLine، ستتم مقاطعتنا ثلاث مرات للذهاب وتنفيذ newLine.

بدورها، تستدعي newLine العملية الجاهزة println، والتي تسبب انعطافاً أخراً أيضاً. لحسن الحظ، فإن Java ماهرة جداً في الحفاظ على مسارٍ يبين مكانها، بحيث تستطيع المتابعة من المكان الذي توقفت عنده في newLine بعد انتهاء تنفيذ println، ثم تعود إلى threeLine، وأخيراً تعود إلى main وهكذا يستطيع البرنامج أن ينتهي.

تقـنياً، لن ينتهي البرنامج عند نهاية main. بدلاً من ذلك، سيتابع التنفيذ في المكان الذي تركه في البرنامج الذي قام باستدعاء main، وهو مفسر Java. يهتم مفسر Java بأشياء مثل حذف النوافذ والتنظيف العام، وبعد ذلك ينتهي البرنامج.

ما هو المغزى من هذه الحكاية المملة؟ عندما تقرأ برنامجاً، لا تقرأ من الأعلى إلى الأسفل. بدلاً من ذلك، تتبع مجرى التنفيذ.

3.8 المعاملات والمتحولات

بعض العمليات الجاهزة التي استخدمناها تتطلب متحولات (arguments)، وهي قيم تعطيها للعملية لتسمح لها بإتمام

عملها. مثلاً، إذا أردت حساب جيب عدد ما، يجب عليك أن تحدد ما هو ذلك العدد. إذن، يأخذ sin قيمة من نوع double كمتحول. لطباعة سلسلة محرفية، عليك أن تعطي تلك السلسة إلى عملية الطباعة، ولهذا فإن println تأخذ String كمتحول.

بعض العمليات تأخذ أكثر من متحول، مثل pow، التي تأخذ متحولين من نوع double، الأساس والأس.

عندما تستخدم عملية، تزودها بالمتحولات. عندما تكتب عملية، تحدد قائمة المعاملات. المعامل (parameter) هو متغير يخزن متحول. تحدد قائمة المعاملات المتحولات المطلوبة للعملية.

مثلاً، تحدد printTwice معاملاً واحداً، s، من النوع String. لقد أسميته s ليبدو أنه من نوع String، لكن من الممكن أن أدعوه بأي اسم مسموح آخر.

public static void printTwice(String s) {
   System.out.println(s);
   System.out.println(s);
}
عندما نستدعي printTwice، علينا تقديم متحول واحد من النوع String.
printTwice("Don't make me say this twice!");
عندما تستدعي عملية، يتم إسناد المتحولات التي أعطيتها للمعاملات. في هذا المثال، يسند المتحول
"Don't make me say this twice!" إلى المعامل s. هذه العملية تدعى تمرير المعاملات (parameter passing) وذلك بسبب تمرير القيم من خارج العملية إلى داخلها.

يمكن أن نمرر أي نوع من العبارات كمتحول، فإذا كنا نملك متغيراً من نوع String، أمكننا تمريره كمتحول:

String argument = "Never say never.";
printTwice(argument);
يجب أن تكون القيمة التي توفرها كمتحول من نفس نوع معامل العملية التي تستدعي. مثلاً، لو جربت هذه التعليمة:
printTwice(17);
ستحصل على رسالة خطأ مثل "cannot find symbol"، "لا يمكن العثور على الشكل"، وهي غير مفيدة كثيراً. السبب هو أن Java تبحث عن عملية باسم printTwice يمكنها أن تأخذ عدداً صحيحاً كمتحول. نظراً لعدم وجود تلك العملية، فلن تتمكن Java من العثور على ذلك "الشكل".

تستطيع System.out.println أن تقبل أي نوع كمتحول. لكن هذه حالة خاصة؛ معظم العمليات ليست بهذه التوافقية.

3.9 المخططات الهرمية

توجد المعاملات والمتغيرات الأخرى داخل عملياتها فقط. ضمن حدود main، لا يوجد شيء اسمه s. إذا حاولت استخدامه، فسيشتكي المجمّع. أيضاً داخل printTwice لا يوجد شيء اسمه argument.

من إحدى الوسائل المستخدمة لتسجيل المكان الذي عرِّف فيه كل متغير هي المخططات الهرمية (stack diagrams). إن المخطط الهرمي للمثال السابق يبدو كما يلي:

لكل عملية يوجد صندوق فضي اللون يدعى إطاراً (frame) يحتوي على معاملات العملية ومتغيراتها. يظهر اسم العملية خارج الإطار. كالعادة، قيمة كل متغير ترسم داخل صندوق يَظهر اسم المتغير بجواره.

3.10 العمليات ذات المعاملات المتعددة

إن البنية المستخدمة في التصريح عن واستدعاء العمليات ذات المعاملات المتعددة تشكل مصدراً شائعاً للأخطاء. أولاً، تذكر أنه عليك تحديد نوع كل معامل. مثلاً

public static void printTime(int hour, int minute) {
   System.out.print(hour);
   System.out.print(":");
   System.out.println(minute);
}
قد يميل البعض لكتابة المعاملات هكذا: int hour, minute، لكن ذلك الشكل ممكن فقط في حالة التصريح عن متغيرات، وليس لقوائم المعاملات.

من مصادر التشويش الأخرى هو أنك لا تحتاج للتصريح عن نوع المتحولات عند استدعاء العملية. ما يلي خاطئ!

int hour = 11;
int minute = 59;
printTime(int hour, int minute);      //WRONG!
في هذه الحالة، تستطيع Java معرفة نوع hour وminute بالنظر إلى تصريحاتهم. ليس ضرورياً كما أنه ليس مشروعاً تضمين أنواعهم عند تمريرهم كمتحولات. الشكل الصحيح للتعليمة هو printTime (hour, minute); .

تمرين 3.1

ارسم مخططاً هرمياً يبين حالة البرنامج عندما يستدعي main عملية printTime مع المتحولين 11 و59.

3.11 العمليات ذات النتائج

ربما تكون لاحظت الآن أن بعض العمليات التي نستخدمها، مثل عمليات Math، تعطي نتائجاً. بينما تقوم عمليات أخرى، مثل println و newLine، بتنفيذ أعمال معينة لكنها لا تعيد قيمة. هذا يطرح بعض الأسئلة:

الإجابة على السؤال الثالث هي "نعم، يمكنك كتابة عمليات ترجع قيماً،" وسنقوم بذلك بعد فصلين. سأترك مهمة الإجابة على السؤالين الأوليين بالتجريب. في الواقع، في أي وقت يكون لديك سؤال عما هو مشروع أو ممنوع في Java، فإن سؤال المجمع طريقة جيدة لمعرفة ذلك.

3.12 المصطلحات

التهيئة: تعليمة تصرح عن متغير جديد وتسند له قيمة في نفس الوقت.

النقطة العائمة: (العدد العشري) نوع متغير (أو قيمة) يمكن أن يحتوي الأعداد الكسرية كما يحوي الأعداد الصحيحة. إن النوع الذي سنستخدمه لأعداد النقطة العائمة هو double.

الصنف: مجموعة مسماة من العمليات. حتى الآن، استخدمنا صنف Math وصنف System، كما كتبنا أصنافاً اسمها Hello و NewLine.

العملية: تعليمات متتابعة من العمليات لها اسم، تنفذ تابعاً مفيداً. العمليات قد تأخذ أو لا تأخذ معاملات، وقد تولد أو لا تولد نتيجة.

المعامل: معلومة تحتاجها العملية حتى تعمل. المعاملات هي متغيرات: فهي تحتوي على قيم ولها أنواع.

المتحول: قيمة توفرها عندما تقوم باستدعاء عملية. هذه القيمة يجب أن تكون من نفس نوع المعامل المقابل.

الإطار: بنية (تمثل بصندوق فضي في مخططات الحالة) تحوي معاملات العملية ومتغيراتها.

الاستدعاء: طلب تنفيذ العملية.

initialization: A statement that declares a new variable and assigns a value to it at the same time.

floating-point: A type of variable (or value) that can contain fractions as well as integers. The floating-point type we will use is double.

class: A named collection of methods. So far, we have used the Math class and the System class, and we have written classes named Hello and NewLine.

method: A named sequence of statements that performs some useful function. Methods may or may not take parameters, and may or may not produce a result.

parameter: A piece of information you provide in order to invoke a method. Parameters are variables: they contain values and have types.

argument: A value that you provide when you invoke a method. This value must have the same type as the corresponding parameter.

frame: A structure (represented by a gray box in stack diagrams) that contains a method's parameters and variables.

invoke: Cause a method to be executed.

3.13 تمرينات

تمرين 3.2

إن الهدف من هذا التمرين هو التدرب على قراءة الشفرة والتأكد من أنك تفهم مجرى التنفيذ لبرنامج متعدد العمليات.

  1. ما هو خرج البرنامج التالي؟ كن دقيقاً بخصوص مواقع المسافات والأسطر الجديدة. مساعدة: ابدأ بشرح ما تفعله ping و baffle بالكلمات عندما يتم استدعاؤها.
  2. ارسم مخططاً هرمياً يبين حالة البرنامج عند استدعاء ping للمرة الأولى.

public static void zoop() {
  baffle();
  System.out.print("You wugga ");
  baffle();
}

public static void main(String[] args) {
  System.out.print("No, I ");
  zoop();
  System.out.print("I ");
  baffle();
}

public static void baffle() {
  System.out.print("wug");
  ping();
}

public static void ping() {
  System.out.println(".");
}

تمرين 3.3

الهدف من هذا التمرين هو التأكد من أنك تفهم كيفية كتابة واستدعاء عملية تأخذ معاملات.

  1. اكتب السطر الأول من عملية باسم zool تأخذ ثلاثة معاملات: واحد int واثنين String.
  2. اكتب السطر من الشفرة التي تستدعي zool، مرر كمتحولات القيمة 11، اسم أول حيوان أليف امتلكته، واسم الشارع الذي كبرت فيه.

تمرين 3.4

الهدف من هذا التمرين هو أخذ الشفرة من تمرين سابق وتغليفها بعملية تأخذ معاملات. عليك البدء مع حل صحيح للتمرين 2.2.

  1. اكتب عملية مسماة printAmerican تأخذ اليوم، والشهر والسنة كمعاملات وتطبعهم بالتنسيق الأمريكي.
  2. اختبر عمليتك باستدعائها من main وتمرير المتحولات المناسبة. يجب أن يكون الخرج كما يلي (عدا أن التاريخ قد يختلف): Wednesday, Septembre 29, 1999
  3. بعد أن تصحح أية أخطاء في printAmerican، اكتب عملية أخرى اسمها printEuropean تطبع التاريخ بالتنسيق الأوروبي.

السابقالفهرسالتالي