تعريف الدوال واستدعاؤها
تعريف الدوال واستدعاؤها
في البرامج التي كتبتها حتى الآن، يعيش كل المنطق داخل main. يصلح ذلك للسكربتات الصغيرة، لكنه يصبح مشكلة سريعًا: يطول الكود، يتسلّل التكرار، وتغيير سلوك واحد يعني البحث في مئات الأسطر. الدوال (Methods) هي جواب Java على ذلك — تتيح لك تسمية كتلة منطق، وإعادة استخدامها في أي مكان، وتغييرها في موضع واحد عند تغيّر المتطلبات.
لماذا تهمّنا الدوال؟
فكّر في الدالة كوصفة مسمّاة. تكتب الوصفة مرّة واحدة ("كيف تصنع الشاي")، ثم تستدعيها بالاسم في كل مرّة تريد الشاي — دون إعادة كتابة الخطوات. بلغة البرمجة، تُقدّم الدوال:
- إعادة الاستخدام — اكتب مرّة واحدة، استدعِ مرّات عديدة.
- القراءة — اسم مثل
calculateTax()يخبر القارئ بما يحدث بالضبط دون قراءة كل سطر بداخلها. - سهولة الصيانة — أصلح خطأً في دالة واحدة وينعكس الإصلاح في كل مكان تُستدعى فيه.
- سهولة الاختبار — الدوال الصغيرة المحدّدة أسهل بكثير في الاختبار المعزول.
تشريح الدالة
لكل دالة Java بنية أساسية واحدة — التوقيع (signature) يليه الجسم (body):
دعنا نفصّل كل جزء:
- محدّد الوصول (Access modifier) — يتحكّم في من يمكنه استدعاء الدالة.
publicتعني الجميع؛privateتعني الكود داخل الفئة نفسها فقط. ستتعلّم محدّدات أخرى لاحقًا؛ استخدمpublic staticالآن حتى تستطيع استدعاء الدالة منmain. - نوع الإرجاع (Return type) — نوع البيانات للقيمة التي ترسلها الدالة إلى المُستدعي. استخدم
voidحين لا ترسل الدالة شيئًا. - اسم الدالة — يتّبع صيغة camelCase بالاصطلاح: يبدأ بحرف صغير وكل كلمة جديدة بحرف كبير (
calculateArea،printGreeting). - قائمة المعاملات (Parameter list) — صفر أو أكثر من المدخلات المكتوبة. قد تكون فارغة، لكن الأقواس مطلوبة دائمًا:
().
أول دالة void
دالة void تُنفّذ إجراءً لكنها لا تُرجع نتيجة للمُستدعي. طباعة عنوان ترحيبي مثال جيد:
تشغيل هذا يطبع العنوان مرّتين. لاحظ كيف تبقى main قصيرة وقابلة للقراءة — إنها تصف ما يحدث بدلًا من تفصيل كل println.
الدوال التي تُرجع قيمة
حين تحسب دالةٌ شيئًا مفيدًا تُصرّح بنوع الإرجاع وتستخدم return لتسليم النتيجة إلى المُستدعي:
يلتقط المُستدعي القيمة المُرجَعة في متغيّر (area) ويمكنه استخدامها في عمل آخر — طباعتها، تخزينها، تمريرها لدالة أخرى، أيًّا كان المطلوب.
double فيجب على الدالة إرجاع double على كل مسار محتمل في الكود. تفرض Java ذلك عند الترجمة، لذا الـ return المفقودة خطأ في الترجمة لا مفاجأة وقت التشغيل.
فهم مكدس الاستدعاء
عند استدعاء دالة، تدفع Java إطارًا جديدًا (stack frame) على مكدس الاستدعاء (call stack). يحمل الإطار المتغيّرات المحلية للدالة ويتتبّع مكان استئناف التنفيذ عند انتهائها. حين تصل إلى return (أو نهاية دالة void)، يُنزع الإطار ويستأنف التنفيذ من حيث تمّ الاستدعاء.
مكدس الاستدعاء مهم عمليًّا لأنه ما تراه في stack trace عند رمي استثناء — كل سطر في التتبّع إطار واحد، يُظهر سلسلة استدعاءات الدوال التي أفضت إلى الخطأ.
ميكانيكا استدعاء الدالة
لاستدعاء دالة اكتب اسمها متبوعًا بالأقواس (مع أي معطيات مطلوبة في الداخل):
يمكنك استدعاء دالة من main، من دالة أخرى، أو حتى من داخل نفسها (العودية — تُغطّى في درس لاحق). كل استدعاء مستقل: تعمل الدالة، تُرجع، ويواصل المُستدعي.
printWelcome دون () لا يستدعي الدالة — بل هو مرجع إلى كائن الدالة، وهذا ليس ما تريده هنا. أضف دائمًا () حتى حين لا توجد معطيات.
تجميع كل شيء
إليك برنامجًا صغيرًا يستخدم دوال void والدوال المُرجِعة معًا:
لاحظ كيف تفوّض printInfo العمل إلى area وperimeter بدلًا من تضمين الحسابات. لكل دالة مسؤولية واحدة واضحة.
الخلاصة
الدالة كتلة كود مُسمّاة قابلة لإعادة الاستخدام، لها نوع إرجاع مُصرَّح (void أو نوع محدّد) واسم وقائمة معاملات اختيارية. استدعاء الدالة يدفع إطارًا جديدًا على مكدس الاستدعاء؛ عند إرجاعها يُنزع الإطار ويستأنف التنفيذ عند المُستدعي. إبقاء الدوال صغيرة ومحدّدة الهدف هو أساس كود Java نظيف قابل للصيانة. في الدرس التالي ستتعمّق في كيفية تواصل المعاملات وقيم الإرجاع لنقل معلومات أغنى بين الدوال والمُستدعين.