الواجهة عقد
تعلن الواجهة عمّا تستطيع فعله الفئة دون أن تذكر كيف. إنها قائمة من توقيعات المنهجيات التي يَعِد كل صنف منفِّذ بالوفاء بها. الهدف هو فك الارتباط: يمكن للشيفرة أن تتعامل مع نوع الواجهة دون أن تهتم بأي صنف ملموس يقف خلفه.
Circle implements Shape تعني أن Circle يجب أن يُعرّف area و perimeter. وبمجرد أن يفعل ذلك، يصبح Circle هو Shape ويمكن تخزينه في متغير من نوع Shape.
أصناف كثيرة، نوع واحد
تتجلى القوة عندما تنفّذ عدة أصناف غير مترابطة الواجهة نفسها. فالشيفرة المكتوبة وفق Shape تتعامل معها جميعاً:
لا تسأل الحلقة أبداً "هل هذا Circle أم Rectangle؟" - بل تستدعي area() ببساطة وتثق بالعقد. وإضافة Triangle لاحقاً لا تتطلب أي تغيير هنا.
تنفيذ واجهات متعددة
يَرِث الصنف صنفاً واحداً فقط، لكنه يستطيع تنفيذ أي عدد من الواجهات - وهكذا تحقق جافا "الوراثة المتعددة" للسلوك بأمان:
اسرد الواجهات مفصولة بفواصل بعد implements. وعلى الصنف أن يلبّيها جميعاً.
منهجيات default و static
منذ جافا 8، يمكن للواجهة أن تتضمن أجسام منهجيات. تمنح منهجية default الأصناف المنفِّذة تنفيذاً جاهزاً ترثه مجاناً (ويمكنها تجاوزه):
تتيح منهجيات default للواجهة أن تتطور - بإضافة منهجية دون كسر كل المنفِّذين الموجودين. أما منهجية الواجهة static فهي على النقيض أداة مساعدة تستدعيها على الواجهة نفسها، مثل Comparator.naturalOrder().
الثوابت
حقول الواجهة هي ضمناً public static final - فهي ثوابت، لا حالة للنسخة:
interface Physics {
double GRAVITY = 9.81; // automatically public static final
}
لا تحتفظ الواجهات تقليدياً بأي حالة لكل كائن؛ وغياب حقول النسخة جزء مما يميزها عن الأصناف.
الواجهات الوظيفية
الواجهة التي تمتلك منهجية مجردة واحدة بالضبط هي واجهة وظيفية، ويمكنك تنفيذها بتعبير لامدا بدلاً من صنف كامل:
هذا هو أساس تعبيرات لامدا في جافا وأنواع java.util.function (مثل Function و Predicate و Supplier وأخواتها). يجعل التوسيم @FunctionalInterface النية صريحة ويتيح للمترجم فرض قاعدة المنهجية الوحيدة.
الواجهة مقابل الصنف المجرد
كلاهما يتيح لك البرمجة وفق تجريد، فمتى تختار أحدهما؟
- الواجهة - قدرة يمكن لأصناف غير مترابطة مشاركتها. يمكن أن يكون كل من
BirdوAirplaneمن نوعFlyable. ويمكن لصنف أن ينفّذ العديد منها. لا حالة للنسخة. - الصنف المجرد - حالة وشيفرة مشتركة بين أصناف وثيقة الصلة. يَرِث كل من
CatوDogالصنفAnimal، فيرثان حقولاً مشتركة ومنهجيات منفَّذة جزئياً. ولا يَرِث الصنف سوى صنف واحد.
ثمة نمط شائع يجمع بينهما: تعرّف واجهة العقد، وينفّذ صنف مجرد الأجزاء المتكررة، بحيث لا تملأ الأصناف الفرعية الملموسة سوى التفاصيل الخاصة.
التالي: الأصناف المجردة
تعرّف الواجهات السلوك دون حالة. أما الأصناف المجردة فتقع بين الواجهات والأصناف الكاملة - إذ يمكنها أن تعلن منهجيات غير منفَّذة و أن تحمل حقولاً ومُنشئات في آنٍ معاً. وذلك موضوع الصفحة التالية.
الأسئلة الشائعة
ما هي الواجهة (interface) في جافا؟
الواجهة هي عقد: مجموعة من توقيعات المنهجيات (والثوابت) التي يَعِد الصنف بتوفيرها. تحدد ما يمكن للصنف فعله، لا كيف يفعله. يستخدم الصنف الكلمة المفتاحية implements لتبني واجهة، ويجب أن يوفر جسماً لكل منهجية مجردة تعلنها الواجهة. تتيح الواجهات استخدام أصناف غير مترابطة بشكل تبادلي عبر نوع مشترك.
ما الفرق بين الواجهة والصنف المجرد في جافا؟
يمكن للصنف أن ينفّذ عدة واجهات، لكنه يَرِث (extends) صنفاً (مجرداً) واحداً فقط. لا تحتفظ الواجهات تقليدياً بأي حالة للنسخة وتعلن السلوك فقط، بينما يمكن للصنف المجرد أن يمتلك حقولاً ومُنشئات ومنطقاً منفَّذاً جزئياً. استخدم واجهة لتعريف قدرة يمكن لعدة أصناف غير مترابطة مشاركتها؛ واستخدم صنفاً مجرداً لمشاركة حالة وشيفرة مشتركة بين أصناف فرعية وثيقة الصلة.
هل يمكن لواجهة جافا أن تحتوي على أجسام منهجيات؟
نعم، منذ جافا 8. توفّر منهجيات الواجهة المعلَّمة بـ default جسماً ترثه الأصناف المنفِّذة (ويمكنها تجاوزه)، بينما توفر منهجيات الواجهة static سلوكاً مساعداً يمكن استدعاؤه على الواجهة نفسها. أما منهجيات الواجهة العادية فلا تزال مجردة -مجرد توقيع- وعلى الأصناف المنفِّذة أن تُعرّفها.