1. ما هي الطريقة الافتراضية ولماذا يجب أن تكون هناك طريقة افتراضية؟
بكل بساطة، يمكن أن تحتوي الواجهة على طرق تنفيذ، وليست هناك حاجة إلى فئة تنفيذ لتنفيذ أساليبها. ما عليك سوى إضافة الكلمة الأساسية الافتراضية أمام اسم الطريقة.
لماذا نحتاج إلى هذه الميزة؟ بادئ ذي بدء، الواجهة السابقة هي سلاح ذو حدين. الميزة هي أنها موجهة نحو التجريد بدلاً من البرمجة المحددة. العيب هو أنه عندما تحتاج الواجهة إلى التعديل، يجب تعديل جميع الفئات التي تنفذ الواجهة لا يحتوي إطار عمل المجموعة الحالي قبل Java 8 على طريقة foreach. الحل الذي يمكن تصوره عادةً هو إضافة طرق وتطبيقات جديدة إلى الواجهات ذات الصلة في JDK. ومع ذلك، بالنسبة للإصدار الذي تم إصداره، لا توجد طريقة لإضافة أساليب جديدة إلى الواجهة دون التأثير على التنفيذ الحالي. لذلك تم تقديم الطريقة الافتراضية. والغرض منها هو حل مشكلة عدم التوافق بين تعديلات الواجهة والتطبيقات الحالية.
مثال بسيط: الواجهة A، تقوم فئة Clazz بتنفيذ الواجهة A.
انسخ رمز الكود كما يلي:
الواجهة العامة أ {
الافتراضي باطلة فو () {
System.out.println("الاتصال بـ A.foo()");
}
}
الطبقة العامة Clazz تنفذ A {
public static void main(String[] args){
Clazz clazz = new Clazz();
clazz.foo();// اتصل بـ A.foo()
}
}
يتم تجميع التعليمات البرمجية على الرغم من أن فئة Clazz لا تطبق طريقة foo(). يتم توفير التنفيذ الافتراضي للطريقة foo() في الواجهة A.
2. مقارنة بين الفئات المجردة والواجهات في Java 8
بعد ظهور هذه الميزة الوظيفية، كان لدى العديد من الطلاب طرق للتنفيذ في واجهات Java 8. في الواقع، لا يزال هناك بعض منها، يرجى الاطلاع على الجدول أدناه للمقارنة. .
| التشابه | الاختلافات |
1. جميعها أنواع مجردة؛ 2. يمكن أن يكون لدى الجميع طرق تنفيذ (الواجهات لم تعمل من قبل)؛ 3. يمكنك تنفيذ جميع الطرق دون تنفيذ الفئات أو الورثة (لم يكن هذا ممكنًا من قبل، الآن لا تحتاج الطرق الافتراضية في الواجهة إلى تنفيذها بواسطة المنفذ) | 1. لا يمكن أن تحتوي الفئات المجردة على وراثة متعددة، بل يمكن للواجهات ذلك (سواء كانت وراثة متعددة الأنواع أو وراثة سلوكية متعددة)؛ 2. تعكس الفئات والواجهات المجردة مفاهيم التصميم المختلفة. في الواقع، تمثل الفئات المجردة العلاقة "is-a"، وتمثل الواجهات العلاقة "like-a". 3. المتغيرات المحددة في الواجهة هي النوع النهائي الثابت العام، ويجب تحديد قيمتها الأولية، لذلك لا يمكن إعادة تعريفها في فئة التنفيذ، ولا يمكن تغيير قيمها في المتغيرات الافتراضية للفئة المجردة إلى النوع المألوف، ويمكن تحديد قيمها في الفئة الفرعية أو إعادة تعيينها. |
3. وصف الصراع في الميراث المتعدد
نظرًا لأنه يمكن تقديم نفس الطريقة من واجهات مختلفة، فمن الطبيعي أن تحدث التعارضات. قواعد تحديد التعارضات بالطرق الافتراضية هي كما يلي:
1. الطريقة المعلنة في الفصل الدراسي لها الأسبقية على أي طريقة افتراضية (الفئات تفوز دائمًا)
2. بخلاف ذلك، سيتم تحديد التنفيذ الأكثر تحديدًا أولاً. على سبيل المثال، في المثال أدناه، يعيد B كتابة طريقة الترحيب الخاصة بـ A.
الإخراج هو: Hello World من B
إذا كنت تريد استدعاء الوظيفة الافتراضية لـ A، فاستخدم الصيغة الجديدة X.super.m(...). بعد ذلك، قم بتعديل الفئة C، وقم بتنفيذ الواجهة A، وأعد كتابة طريقة الترحيب، كما هو موضح أدناه:
انسخ رمز الكود كما يلي:
الطبقة العامة C تنفذ A {
@تجاوز
مرحبا الفراغ العام () {
A.super.hello();
}
public static void main(String[] args){
جديد C().hello();
}
}
الإخراج هو: Hello World من A
4. ملخص
توفر لنا الطريقة الافتراضية سهولة تعديل الواجهة دون تدمير بنية فئة التنفيذ الأصلية. حاليًا، استخدم إطار عمل Java 8 الطرق الافتراضية على نطاق واسع لتحسينه عندما بدأنا أخيرًا في استخدام تعبير lambdas Java 8، يتم توفيره من أجل الحصول على تجربة انتقال سلسة. ربما سنرى المزيد من تطبيقات الطرق الافتراضية في تصميم واجهة برمجة التطبيقات (API) في المستقبل.