الاستدعاء الذاتي في Java
اكتب دالة اسمها down تأخذ int واحدًا اسمه n. إذا كان n يساوي 0 أو أقل، توقف بـ return; فارغ. وإلا اطبع n ثم استدعِ down(n - 1) من داخل الدالة نفسها. من main استدعِ down(3);. يجب أن تظهر الشاشة ثلاثة أسطر: 3، ثم 2، ثم 1. الدالة تستدعي نفسها برقم أصغر حتى ينهي التوقف السلسلة. ذلك الاستدعاء الذاتي مع توقف هو ما تعلّمه هذه الصفحة.
دالة تستدعي نفسها
في صفحة النطاق، شغّلت mark مرة وانتهت. هنا down تعمل ثم تبدأ down أخرى بحجة جديدة قبل أن تنتهي الدعوة الأولى تمامًا. لكل دعوة n خاص بها. تنتهي السلسلة فقط عندما تصطدم دعوة بالتوقف.
أنشئ ملف برنامج صغيرًا باسم Ladder.java. يجب أن يطابق public class في السطر الأول اسم الملف: public class Ladder. لا تُبقِ اسم فئة قديمًا مثل Gate أو Sign في هذا الملف؛ المترجم يتوقع أن يتوافق اسم الفئة مع اسم الملف.
خارج main، وما زلت داخل أقواس الفئة المجعدة، اكتب static void down(int n). في هذه الصفحة أبقِ void: كل خطوة تطبع ولا شيء يحتاج أن يعود عبر return مُنَوَّع. التوقف يستخدم return; بلا قيمة — ينهي هذه الدعوة فقط. احفظ الملف قبل الترجمة. البرنامج الكامل الأول في الصندوق التالي.
Ladder.java مع down
هذه النسخة التي تترجمها أولًا. main يحمل استدعاءً واحدًا. down تحمل التوقف والطباعة والاستدعاء الذاتي.
public class Ladder {
public static void main(String[] args) {
down(3);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
من المجلد الذي يحوي Ladder.java نفّذ javac Ladder.java. عندما تتوافق الأقواس والأقواس المجعدة والفواصل المنقوطة، لا يكتب javac سطرًا من عنده. ثم نفّذ java Ladder — لا java Ladder.java. احذف لاحقة .java من الأمر الثاني. الأمران نفسهما يعملان على Windows وmacOS. يجب أن يطبع البرنامج ثلاثة أسطر ويتوقف: 3، ثم 2، ثم 1. لا يطلب منك الكتابة. إذا انتظر الطرفية إدخال لوحة المفاتيح، فما زال استدعاء nextLine من تمرين قديم في الملف. احذفه وأبقِ down(3); مع دالة down أعلاه.
سر على التشغيل مرة بالترتيب. تبدأ Java من main. الاستدعاء down(3) يدخل وn يساوي 3. ذلك أكبر من 0، فتطبع الدالة 3 ثم تستدعي down(2). الدعوة الثانية تطبع 2 ثم تستدعي down(1). الثالثة تطبع 1 ثم تستدعي down(0). الدعوة ذات 0 تصطدم بـ n <= 0 وتعود بلا طباعة. تنتهي السلسلة. الشاشة تحتفظ بالأسطر الثلاثة المطبوعة.
كل واحدة من تلك الدعوات مرور منفصل عبر نفس نص الدالة. المرور الأول ما زال لديه عمل بعد بدء down(2) — أي الإنهاء بعد عودة الدعوة الداخلية. لا تكتب أربعة أسماء دوال مختلفة. تكتب دالة واحدة وتدع الحجة الأصغر تحمل التقدم نحو التوقف.
إذا غيّرت البداية إلى down(2); يجب أن تظهر الشاشة 2 ثم 1. جسم الدالة يبقى نفسه؛ فقط الحجة الأولى تتغير فتكون السلسلة أقصر. البدء بـ down(4); يجب أن يظهر أربعة أسطر: 4، 3، 2، 1. مرة أخرى الجسم بلا تغيير؛ فقط main يختار القيمة الأولى.
ضع التوقف أولًا
يجب فحص التوقف قبل الطباعة وقبل الاستدعاء الذاتي. إذا طبعت أولًا ولم تختبر n أبدًا، أو إذا استدعيت دائمًا down(n) بنفس القيمة، لا ينتهي البرنامج. أبقِ كتلة if (n <= 0) في أعلى الدالة بهذا الشكل للمبتدئين.
public class Ladder {
public static void main(String[] args) {
down(2);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
ترجم وشغّل من جديد: javac Ladder.java، ثم java Ladder. تظهر الشاشة 2 ثم 1. التوقف ما زال ينهي السلسلة عندما يصل n إلى 0. كتابة down(n) بدل down(n - 1) ترسل الرقم نفسه مرارًا. عندئذ قد يعمل البرنامج حتى يوقفه النظام. الحجة الأصغر جزء من الفكرة: كل دعوة يجب أن تتقدم نحو التوقف.
فكّر في التوقف كباب الخروج. الطباعة عمل هذه الخطوة. الاستدعاء الذاتي الخطوة التالية. بلا باب، كل خطوة تفتح أخرى بلا نهاية. إذا استخدمت الخطوة التالية نفس n، لا تمشي نحو الباب أبدًا. الخطأان يبدوان مختلفين في المصدر، لكن كليهما يرفضان الإنهاء النظيف بهذا الشكل للمبتدئين.
سلسلة الاستدعاء بجانب الشاشة
اقرأ استدعاء بداية بجانب الأسطر التي ينتجها. كل صف زيارة لـ down ما زالت تطبع.
📊 down call chain for down(3)
| الاستدعاء | قيمة n | سطر الشاشة |
|---|---|---|
أول down(3) |
3 |
3 |
ثم down(2) |
2 |
2 |
ثم down(1) |
1 |
1 |
ثم down(0) |
0 |
(بلا سطر — توقف) |
خلط شائع هو ترك التوقف. عندئذ كل دعوة تطبع وتستدعي من جديد إلى الأبد. خلط آخر هو الطباعة بعد الاستدعاء الذاتي بدل قبله. في هذه الصفحة تأتي الطباعة أولًا، فالشاشة تعدّ تنازليًا. إذا نقلت println تحت down(n - 1) يتغير ترتيب الأسطر — أبقِ الطباعة فوق الاستدعاء الذاتي للعدّ التنازلي هنا.
نطاق الصفحة السابقة ما زال مهمًا قليلًا: n لكل دعوة هو معامل تلك الدعوة. n للدعوة الخارجية لا يعيد كتابة نفسه عندما تعمل الداخلية. للداخلية n منفصل. عندما تعود الداخلية، تتابع الخارجية من السطر بعد الاستدعاء الذاتي — وفي هذه الصفحة ذلك ببساطة نهاية الدالة.
عرض Gate قديم مع mark(4) قد يبقى في نفس الملف ويشوّش الشاشة إن كان main ما زال يستدعي mark. صفِّ main إلى down(3); أو down(2); وأنت تتعلم هذه الصفحة. لا تُعرِّف down داخل أقواس main المجعدة. الدوال تجلس داخل الفئة بجانب main.
كتابة System.out.println("down"); في main تطبع كلمة down. لا تبدأ السلسلة. أبقِ down(3); عندما تريد أسطر العدّ التنازلي الثلاثة.
شكل آخر: التوقف لا يطبع شيئًا
رأيت أن الدعوة ذات 0 تعود بهدوء. يمكنك أيضًا التمرن بقيمة بداية 1. يجب أن تظهر الشاشة سطرًا واحدًا: 1. ثم الدعوة التالية down(0) التي تتوقف.
public class Ladder {
public static void main(String[] args) {
down(1);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
بعد javac Ladder.java وjava Ladder تظهر الشاشة سطرًا واحدًا: 1. نفس جسم الدالة يغطي down(3) وdown(2) وdown(1). فقط الحجة الأولى في main تتغير. ذلك يكفي لهذه الصفحة للمبتدئين. أفكار أعمق مثل إرجاع مجموع من الاستدعاء الذاتي تنتظر دورات لاحقة؛ هنا الهدف الاستدعاء الذاتي والحجة الأصغر والتوقف.
إذا لم تظهر الشاشة شيئًا، تحقق مما إذا كان main ما زال يستدعي شيئًا آخر، أو مما إذا كان اختبار التوقف خاطئًا — مثلًا if (n >= 0) يتوقف قبل أي طباعة عند البدء بـ n موجب. أبقِ n <= 0 خروجًا هادئًا، وأبقِ بداية موجبة في main ليظهر سطر واحد على الأقل.
قبل classes
يمكنك كتابة down(int n)، والتوقف عندما يكون n 0 أو أقل، وطباعة n ثم استدعاء down(n - 1). من main، استدعاء واحد يبدأ السلسلة كلها. تظهر الشاشة أسطر العدّ التنازلي. دالة لا تتقدم أبدًا نحو التوقف لا تنتهي. الصفحة التالية هي classes؛ هناك تبدأ بناء أنواع بحقول أبعد من صفحات الدوال static هذه.
🧠 اختبر معرفتك
اختبر معرفتك
تحدى نفسك مع هذا الاختبار التفاعلي واكتشف مدى فهمك للموضوع
📝 التعليمات
- اقرأ كل سؤال بعناية
- اختر أفضل إجابة لكل سؤال
- يمكنك إعادة الاختبار عدة مرات كما تريد
- سيتم عرض تقدمك في الأعلى