ما هي الطريقة الافتراضية؟
بعد إصدار Java 8 ، يمكن إضافة طرق جديدة إلى الواجهة ، ولكن يمكن أن تكون الواجهة متوافقة مع فئة التنفيذ الخاصة بها. هذا مهم للغاية لأن مكتبة الفصل التي تطورها قد تستخدم على نطاق واسع من قبل العديد من المطورين. قبل Java 8 ، بعد إصدار واجهة في مكتبة الفصل ، إذا تمت إضافة طريقة جديدة إلى الواجهة ، فإن التطبيقات التي تنفذ هذه الواجهة ستكون عرضة لخطر التعطل باستخدام الإصدار الجديد من الواجهة.
مع Java 8 ، ألا يوجد مثل هذا الخطر؟ الجواب لا.
قد تجعل إضافة طريقة افتراضية إلى واجهة بعض فئات التنفيذ غير متوفرة.
أولاً ، دعونا نلقي نظرة على تفاصيل الطريقة الافتراضية.
في Java 8 ، يمكن تنفيذ الطرق في الواجهات (يمكن أيضًا تنفيذ الطرق الثابتة في Java 8 في واجهات ، ولكن هذا موضوع آخر). تسمى الطريقة التي تم تنفيذها في الواجهة الطريقة الافتراضية ، والتي يتم تحديدها بواسطة الكلمة الرئيسية الافتراضية كمعدل. عندما يقوم الفصل بتنفيذ واجهة ، يمكنه تطبيق الأساليب التي تم تنفيذها في الواجهة ، ولكن هذا ليس ضروريًا. سوف يرث هذا الفئة الطريقة الافتراضية. هذا هو السبب عندما تتغير الواجهة ، لا يلزم تغيير فئة التنفيذ.
ماذا عن الوقت لروث أكثر؟
تصبح الأمور معقدة عندما ينفذ الفصل أكثر من واجهات (على سبيل المثال ، اثنان) وهذه الواجهات لها نفس الطريقة الافتراضية. ما هي الطريقة الافتراضية التي يرثها الفصل؟ لا أحد منهم! في هذه الحالة ، يجب على الفئة تنفيذ الطريقة الافتراضية (فقط) بمفرده (مباشرة أو ورث الفئات ذات المستوى الأعلى على الشجرة).
وينطبق الشيء نفسه عندما تنفذ واجهة واحدة من الطريقة الافتراضية وتعلن الواجهة الأخرى أن الطريقة الافتراضية مجردة. تحاول Java 8 تجنب الأشياء غير الواضحة والحفاظ عليها صارمة. إذا تم الإعلان عن طريقة في واجهات متعددة ، فلن يتم مورث أي تطبيق افتراضي وستحصل على خطأ في وقت الترجمة.
ومع ذلك ، إذا قمت بتجميع الفصل الخاص بك ، فلن تكون هناك أخطاء في وقت التجميع. في هذه المرحلة ، Java 8 غير متسقة. لها أسبابها الخاصة ، لأسباب مختلفة. لا أريد أن أشرح بالتفصيل أو مناقشته بتعمق هنا (لأنه: تم إصدار الإصدار والمناقشة طويلة جدًا ، ولم يناقش هذا النظام الأساسي مثل هذا).
يمكن أن يعمل الفصل بشكل طبيعي في الحالة أعلاه. ومع ذلك ، لا يمكن إعادة ترجمة مع واجهات معدلة ، ولكن لا يزال من الممكن تشغيلها مع واجهات قديمة. التالي
عندما توفر كلا الوبيدين تطبيقات افتراضية لنفس الطريقة ، لا يمكن استدعاء هذه الطريقة إلا إذا كانت فئة التنفيذ تنفذ أيضًا الطريقة الافتراضية (إما تنفذها مباشرة أو ترث الفئة ذات المستوى الأعلى على الشجرة للتنفيذ).
ومع ذلك ، فإن هذه الفئة متوافقة. يمكن تحميله مع واجهات جديدة ، أو حتى تنفذ ، طالما أنها لا تسمي طريقة لها تنفيذ افتراضي في كلا الواجهات.
رمز مثال
لإظهار المثال أعلاه ، قمت بإنشاء دليل اختبار لـ C.Java ، الذي يحتوي على 3 أشرطة فرعية أدناه ، والتي تستخدم لتخزين i1.java و i2.java. يحتوي دليل الاختبار على رمز المصدر لـ C.Java من الفئة C. يحتوي الدليل الأساسي على الواجهة إلى الإصدار الذي يمكن تجميعه وتشغيله. يحتوي I1 على طريقة M () التي يتم تنفيذها افتراضيًا ، ولا يحتوي I2 على أي طرق.
تحتوي فئة التنفيذ على الطريقة الرئيسية ، حتى نتمكن من تنفيذها في الاختبار. سيتحقق مما إذا كانت هناك معلمات سطر الأوامر ، بحيث يمكننا بسهولة تنفيذ الاختبارات التي تستدعي M () وعدم استدعاء M ().
تنفذ الفئة العامة C i1 ، i2 {public static void main (string [] args) {c c = new c () ؛ if (args.length == 0) {cm () ؛ }}} الواجهة العامة i1 {default void m () {system.out.println ("hello interface 1") ؛ }} الواجهة العامة i2 {}استخدم سطر الأوامر التالي لتجميع وتشغيل:
Javac -cp .: Base C.Javajava -Cp .: Base Chello Interface 1
يحتوي الدليل المتوافق على واجهة I2 مع الطريقة التجريدية M () وواجهة I1 غير المعدلة.
الواجهة العامة i2 {void m () ؛}لا يمكن استخدام هذا لتجميع الفئة C:
Javac -cp .: التوافق C.Javac.java:1: الخطأ: C ليس مجردة ولا يتغلب على الطريقة التجريدية M () في I2Public Class C الأدوات I1 ، I2 { ^ 1 خطأرسالة الخطأ دقيقة للغاية. نظرًا لأن لدينا c.class التي تم الحصول عليها من التجميع السابق ، إذا قامنا بتجميع الواجهة في الدليل المتوافق ، فستظل نحصل على واجهتين يمكنهما تشغيل فئة التنفيذ:
Javac متوافق/i*.javajava -cp .: واجهة Chello متوافقة 1
الدليل الثالث يسمى خطأ ، وواجهة I2 الواردة أيضًا تحدد طريقة M ():
الواجهة العامة i2 {افتراضي void m () {system.out.println ("Hello Interface 2") ؛ }}لا ينبغي لنا أن نتعب من تجميعها. على الرغم من أن طريقة M () محددة مرتين ، إلا أنه لا يزال من الممكن تشغيل فئة التنفيذ طالما أنها لا تسمي الطريقة التي تم تعريفها عدة مرات ، ولكن طالما نسمي طريقة M () ، فسوف تفشل على الفور. فيما يلي معلمات سطر الأوامر التي نستخدمها:
Javac خطأ/*. Javajava -cp .: خاطئ C استثناء في الموضوع "Main" java.lang.incompatibleclasschangeerror: طرق افتراضية متضاربة: i1.m i2.m في cm (cm (cmava) في c.main (
ختاماً
عندما تقوم بتنفيذ مكتبة الفصل التي تضيف التنفيذ الافتراضي إلى الواجهة إلى بيئة Java 8 ، لن تكون هناك مشكلة بشكل عام. على الأقل هذا هو ما يعتقده مطورو مكتبة Java8 عند إضافة طرق افتراضية إلى فئات التجميع. لا تزال التطبيقات التي تستخدم مكتبة الفصل الخاصة بك تعتمد على مكتبة فئة Java7 دون الطريقة الافتراضية. عند استخدام وتعديل مكتبات فئة مختلفة متعددة ، هناك فرصة صغيرة للصراع. كيف يمكنني تجنب ذلك؟
تصميم مكتبة الفصل الخاص بك كما كان من قبل. لا تأخذ الأمر بخفة عندما تتمكن من الاعتماد على الطريقة الافتراضية. لا تستخدمه على أنه ضروري للغاية. اختر اسم الطريقة بحكمة لتجنب النزاعات مع واجهات أخرى. سوف نتعلم كيفية استخدام هذه الميزة للتطوير في برمجة Java.
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.