تنفيذ واجهات متعددة
تنفيذ واجهات متعددة
من أقوى ميزات الواجهات في Java أنّ الصنف الواحد يمكنه تنفيذ أيّ عدد من الواجهات. هذا يتجاوز قيد الوراثة الأحادية في الأصناف، ويتيح لك تركيب سلوكيّات من عقود مستقلة متعددة. في هذا الدرس ستتعلم كيفية ربط واجهات متعددة، والأهمّ، كيفية التعامل مع التعارضات التي تنشأ حين تُعرّف إحدى الواجهتين تابع default بنفس التوقيع.
لماذا ننفّذ واجهات متعددة؟
تخيّل كائنًا من الواقع مثل SmartDevice. قد يحتاج إلى أن يكون قابلًا للطباعة، وقابلًا للتسلسل، وقابلًا للتحكم عن بُعد — ثلاث قدرات مختلفة تمامًا. لا شيء منها هو صنف أب؛ جميعها أدوار يؤدّيها الصنف. الواجهات تُمثّل الأدوار بصورة مثالية لأنّها تعلن عقدًا دون فرض تراتبية صنفية.
الصياغة الأساسية
اذكر كل واجهة بعد الكلمة المحجوزة implements مفصولةً بفاصلة:
يفرض المُصرِّف تنفيذ كل تابع مجرّد من كل واجهة. إن أغفلت تنفيذ تابع واحد لن يُصرَّف الصنف.
تعدد الأشكال عبر واجهات متعددة
يمكن الآن إسناد كائن Report لمتغيّرات من أيٍّ من الثلاث أنواع. كل مرجع يكشف فقط التوابع الخاصة بنوعه المُعلَن:
هذا هو تعدد الأشكال الاعتيادي. الكائن الفعلي دائمًا Report، لكن مرجع الواجهة يُقيّد القدرات التي يراها المستدعي — أداة مفيدة لتضييق النطاق.
تعارض توابع default
تبدأ المشكلات حين تُعرّف واجهتان تابع default بنفس الاسم وقائمة المعاملات. لا يستطيع المُصرِّف اختيار واحدة منهما بصمت، لذا يجبرك على حل التعارض صراحةً.
إن كنت تفضّل التفويض لأحد التنفيذات الافتراضية الموجودة بدلًا من كتابة تنفيذ جديد، استخدم الصياغة الخاصة InterfaceName.super.method():
مثال عملي: مكوّن نظام إضافات
إليك سيناريو أكثر واقعية. تخيّل نظام إضافات حيث يجب على كل إضافة دعم خطّافات دورة الحياة وكذلك الوعي بالإصدار:
ملخّص القواعد
- يمكن للصنف تنفيذ أيّ عدد من الواجهات — لا حدّ لذلك.
- يجب تنفيذ كل تابع مجرّد من كل واجهة (أو يُعلَن الصنف نفسه
abstract). - إن قدّمت واجهتان تابع
defaultبنفس التوقيع، يجب على الصنف المنفِّذ تجاوزه. - استخدم
InterfaceName.super.method()لاستدعاء التنفيذ الافتراضي لواجهة بعينها من داخل التجاوز. - إن كانت واجهة واحدة فقط تملك التابع الافتراضي والأخرى تعلنه مجرّدًا، يفوز التنفيذ الافتراضي بلا تعارض.
الخلاصة
تنفيذ واجهات متعددة هو إجابة Java عن الوراثة المتعددة. تُدرج كل الواجهات بعد implements، وتوفّر جسمًا لكل تابع مجرّد، وتحلّ صراحةً أيّ تعارض في أسماء توابع default بتجاوز التابع المتعارِض. تُتيح لك الصياغة InterfaceName.super.method() استدعاء التنفيذ الافتراضي لأيٍّ من الواجهتين كلبنة بناء داخل تجاوزك. تمنحك هذه القواعد معًا تصاميم مرنة قابلة للتركيب دون غموض مشاكل الوراثة المتعددة من الأصناف في لغات أخرى.