الأساليب الافتراضية (Default Methods)
الأساليب الافتراضية (Default Methods)
قدّمت Java 8 إحدى أهم الإضافات العملية على الواجهات: الأساليب الافتراضية. الأسلوب الافتراضي هو أسلوب يُعلَن مباشرة داخل الواجهة ويحمل جسمًا برمجيًا ملموسًا. أي صنف ينفّذ الواجهة يرث هذا التنفيذ الافتراضي تلقائيًا — لكنه يظلّ حرًا في تجاوزه.
المشكلة التي تحلّها الأساليب الافتراضية
قبل Java 8، لم تستطع الواجهات احتواء سوى توقيعات الأساليب المجرّدة. أوجد هذا مشكلة مؤلمة في إصدارات المكتبات: بمجرّد أن تنشر مكتبة واجهةً ويُنفّذها كود حقيقي، لم يكن بالإمكان إضافة أسلوب جديد إلى تلك الواجهة دون كسر كل منفّذ موجود. كل صنف قائم سيفشل فجأة في الترجمة لأنه يفتقر إلى الأسلوب الجديد.
واجه إطار مجموعات Java هذه المشكلة بالضبط حين وصلت تعابير lambda والتدفقات في Java 8. احتاجت التسلسلية الهرمية لـCollection إلى أساليب جديدة مثل forEach وstream وremoveIf. بدون الأساليب الافتراضية، كانت إضافة أيٍّ منها إلى Iterable أو Collection ستكسر ملايين البرامج حول العالم.
الصياغة
استخدم الكلمة المفتاحية default قبل نوع الإرجاع داخل جسم الواجهة:
أي صنف ينفّذ Greeter يجب أن يوفّر getName()، لكنه يحصل على greet() مجانًا:
تجاوز الأسلوب الافتراضي
يستطيع المنفّذ دائمًا اختيار تجاوز الأسلوب الافتراضي بمنطقه الخاص، تمامًا كتجاوز أي أسلوب آخر:
استدعاء الأسلوب الافتراضي من الواجهة داخل التجاوز
إن أردت توسيع السلوك الافتراضي بدلًا من استبداله، استخدم InterfaceName.super.methodName():
مثال واقعي: تطوير واجهة إضافات
تخيّل أنك تشحن مكتبة بهذه الواجهة في الإصدار 1.0:
عشرات المستخدمين ينفّذونها. في الإصدار 1.1 تريد أن يدعم كل معالج عملية معالجة مجمّعة، لكنك لا تريد كسر الكود الموجود. الأسلوب الافتراضي هو الحل:
يُعيد جميع المنفّذين الحاليين الترجمة دون تغييرات. يحصلون على processBatch تلقائيًا — فهي تستدعي process مرة لكل عنصر باستخدام أي منطق يمتلكه الصنف الفرعي. يستطيع المنفّذون ذوو الأداء العالي تجاوزها بنهج مُحسَّن.
مشكلة الماسة وقواعد الحلّ
بما أن صنفًا واحدًا يستطيع تنفيذ واجهات متعددة (يُغطّى في الدرس التالي)، قد توفّر واجهتان معًا أسلوبًا افتراضيًا بنفس التوقيع. لا تختار Java واحدًا بصمت — يجبرك المترجم على حلّ التعارض:
ما الأساليب الافتراضية ليست كذلك
- هي ليست بديلًا عن الصنف المجرّد. لا تستطيع الاحتفاظ بحالة نسخة (لا حقول).
- هي ليست مخصّصة لإضافة منطق أعمال إلى الواجهة. غرضها الأساسي هو تطوير الواجهة البرمجية ومساعدات الراحة.
- هي ليست نفس أساليب
staticفي الواجهات (تلك تنتمي لنوع الواجهة نفسه لا للنسخ — يُغطّى في الدرس التالي).
الخلاصة
تمنح الأساليب الافتراضية الواجهاتِ جسمًا ملموسًا لأسلوب أو أكثر. وجودها يخدم أساسًا تمكين الواجهات القائمة من اكتساب قدرات جديدة دون كسر كل صنف ينفّذها. يملك الصنف المنفّذ دائمًا الكلمة الأخيرة: يرث الافتراضي، أو يتجاوزه، أو يستدعيه عبر InterfaceName.super.method() مضيفًا منطقه الخاص. حين تتعارض واجهتان على نفس اسم الأسلوب الافتراضي، يطالب المترجم بحلٍّ صريح.