الكلمة المحجوزة super وتسلسل المنشئات
الكلمة المحجوزة super وتسلسل المنشئات
في الدرس السابق تعلّمت أن الفئة الابن تستخدم extends للوراثة من الفئة الأب. لكن ماذا يحدث حين يحتاج كلٌّ من الأب والابن إلى التهيئة؟ هنا يأتي دور الكلمة المحجوزة super. تتيح لك super العبور عبر حدود الوراثة والتواصل مباشرةً مع الأب — باستدعاء منشئه أو استدعاء إحدى دواله.
لماذا تهمّنا منشئات الأب؟
يجب أن يكون كل كائن في Java مهيَّأً تهيئةً كاملة قبل استخدامه. حين تُنشئ كائنًا من الفئة الابن، تتواجد حقول الفئة الأب داخل ذلك الكائن أيضًا، لذا يجب أن يعمل منشئ الأب أولًا لتهيئتها. تفرض Java ذلك تلقائيًا، لكنّك تحتاج إلى فهم القواعد لكتابة كود صحيح.
استدعاء منشئ الأب باستخدام super()
استخدم super(...) كأوّل عبارة داخل منشئ الابن لتمرير الوسائط إلى منشئ الأب.
الناتج:
لاحظ الترتيب: منشئ الأب يعمل دائمًا قبل جسم الابن. هذا يضمن أن حقول الأب جاهزة بمجرّد أن يواصل منشئ الابن تنفيذه.
super() (النسخة بدون وسائط) — لكن فقط إن كان للأب منشئ بدون وسائط. إن كان الأب يتطلّب وسائط ونسيت super(...)، لن يُجمَّع الكود.
ماذا لو لم تكتب super() صراحةً؟
حين يملك الأب منشئًا بدون وسائط، تُضيف Java نداء super() ضمنيًا تلقائيًا:
تشغيل new Car() يطبع "تم إنشاء Vehicle" أولًا ثم "تم إنشاء Car". النداء الضمني يتّبع نفس القاعدة — الأب يعمل أولًا.
استدعاء دالة الأب باستخدام super.method()
super ليست للمنشئات فقط. يمكنك استخدامها داخل دالة لاستدعاء نسخة الأب من تلك الدالة. هذا مفيد بشكل خاص حين تُلغي دالةً لكنّك تريد إعادة استخدام منطق الأب:
الناتج:
super() (بأقواس كعبارة مستقلة) تستدعي منشئ الأب ويجب أن تكون السطر الأوّل. super.someMethod() تستدعي دالة الأب ويمكن أن تظهر في أي مكان داخل جسم دالة الابن.
ترتيب تنفيذ المنشئات في تسلسل هرمي أعمق
تعمل السلسلة بنفس الطريقة بغضّ النظر عن عدد مستويات الوراثة. كل مستوى يستدعي super() أولًا، فيسير التنفيذ من أعلى الهرم إلى أسفله:
تبدأ Java دائمًا من الجدّ الأعلى وتنحدر إلى الأسفل. يمكنك الاعتماد على هذا الترتيب: بحلول وقت تنفيذ جسم منشئك، يكون كل أب فوقك قد انتهى من تهيئته.
java.lang.Object على رأس كل هرم وراثة. منشئها بدون وسائط هو أوّل شيء يُستدعى دائمًا حتى لو لم تكتب super() أبدًا — وهذا هو السبب في أنك تستطيع استدعاء دوال مثل toString() وequals() على أي كائن Java دون استيراد أي شيء.
مثال عملي: هرم الموظفين
الناتج: Alice راتبه 6500.0
هنا super(name, baseSalary) ترسل البيانات المشتركة إلى Employee، وsuper.calculatePay() تُعيد استخدام منطق الراتب الأساسي حتى لا يكرّر Manager ذلك المنطق.
الخلاصة
super(args)تستدعي منشئ الأب — يجب أن تكون أوّل سطر في أي منشئ ابن.- إن حذفتها، تُدرج Java ضمنيًا
super()بدون وسائط؛ إن لم يكن للأب منشئ كذلك فسيحدث خطأ وقت الترجمة. super.method()تستدعي نسخة الأب من دالة ويمكن أن تظهر في أي مكان داخل دالة الابن.- تُنفَّذ المنشئات دائمًا من أعلى الهرم إلى أسفله، فحقول الأب تكون جاهزة دائمًا قبل تشغيل كود الابن.