مميزات واجهة مع الأساليب الافتراضية مقابل فئة الملخص في Java 8




مميزات لغة الجافا (11)

بما أن Java 8 تسمح بالتنفيذ الافتراضي للطرق في واجهة تسمى Default Methods ، يبدو أن هناك تشويشًا بين متى أستخدم abstract class .

لذا متى يجب استخدام الواجهة بالطرق الافتراضية ومتى يجب استخدام فئة تجريدية؟ هل ما زالت الطبقات المجردة مفيدة في هذا السيناريو؟


هذان مختلفان تمامًا:

الطرق الافتراضية هي إضافة وظائف خارجية للفئات الموجودة دون تغيير حالتها.

والفصول التجريدية هي نوع عادي من الميراث ، فهي فئات عادية يُقصد منها توسيعها.


ريمي فوراكس القاعدة أنت لا تصمم مع الطبقات مجردة. يمكنك تصميم التطبيق الخاص بك مع واجهات . Watever هو إصدار Java ، بغض النظر عن اللغة. مدعومة من قبل مبدأ الفصل nterface في مبادئ SOLID

يمكنك في وقت لاحق استخدام الطبقات Abstract لإدخال رمز. الآن مع Java 8 يمكنك القيام بذلك مباشرة في الواجهة. هذا مرفق وليس أكثر.


تعمل الطرق الافتراضية في واجهة Java على تمكين تطوير الواجهة .

بالنظر إلى واجهة موجودة ، إذا كنت ترغب في إضافة طريقة إليها دون كسر التوافق الثنائي مع الإصدارات القديمة للواجهة ، فلديك خياران في يديك: إضافة طريقة افتراضية أو طريقة ثابتة. في الواقع ، فإن أي طريقة مجردة تضاف إلى الواجهة يجب أن يتم تنفيذها من خلال الطبقات أو الواجهات التي تقوم بتنفيذ هذه الواجهة.

طريقة ثابتة فريدة لفئة. تعتبر الطريقة الافتراضية فريدة لمثيل الفصل الدراسي.

إذا قمت بإضافة طريقة افتراضية لواجهة موجودة ، فلا تحتاج الفئات والواجهات التي تقوم بتطبيق هذه الواجهة إلى تنفيذها. يستطيعون

  • تنفيذ الطريقة الافتراضية ، ويتجاوز التطبيق في واجهة التنفيذ.
  • إعادة إعلان الطريقة (بدون التنفيذ) مما يجعلها مجردة.
  • القيام بأي شيء (ثم يتم ببساطة توارثت الطريقة الافتراضية من واجهة تنفيذها).

المزيد حول هذا الموضوع here .


هناك بعض الاختلافات التقنية. لا يزال بإمكان الطبقات المجردة عمل المزيد بالمقارنة مع واجهات Java 8:

  1. الطبقة المجردة يمكن أن يكون لها منشئ.
  2. الطبقات المجردة هي أكثر تنظيما ويمكن أن تعقد دولة.

من الناحية المفاهيمية ، فإن الغرض الرئيسي من أساليب المدافع هو التوافق مع الإصدارات السابقة بعد إدخال ميزات جديدة (مثل وظائف lambda) في Java 8.


عندما يكون لدينا خيار بين الطبقة التجريدية والواجهة ، يجب أن نفضل دائمًا (تقريبًا) الطرق الافتراضية (المعروفة أيضًا باسم المدافع أو الإضافات الظاهرية).

  1. وضعت الطرق الافتراضية حدا للنمط الكلاسيكي للواجهة وفئة رفيقة تطبق معظم أو كل الطرق في هذه الواجهة. مثال على ذلك هو Collection and AbstractCollection . الآن يجب علينا تنفيذ الأساليب في الواجهة نفسها لتوفير وظائف افتراضية. تحتوي الفئات التي تقوم بتطبيق الواجهة على خيار تجاوز الأساليب أو توارث التنفيذ الافتراضي.
  2. استخدام آخر مهم من الأساليب الافتراضية هو interface evolution . لنفترض أن لديّ كرة من الدرجة كـ:

    public class Ball implements Collection { ... }

الآن في Java 8 ميزة جديدة يتم عرضها في المقدمة. يمكننا الحصول على تدفق باستخدام طريقة stream المضافة إلى الواجهة. إذا لم يكن stream طريقة افتراضية ، فكل التطبيقات الخاصة بواجهة Collection قد تكون مكسورة لأنها لن تقوم بتنفيذ هذه الطريقة الجديدة. إن إضافة طريقة غير افتراضية إلى واجهة ليست source-compatible .

لكن لنفترض أننا لا نقوم بإعادة تجميع الصف واستخدام ملف جرة قديم يحتوي على هذا الصنف. سيتم تحميل الطبقة بشكل جيد بدون هذه الطريقة المفقودة ، يمكن إنشاء المثيلات ويبدو أن كل شيء يعمل بشكل جيد. ولكن إذا كان البرنامج يستدعي أسلوب stream على سبيل المثال من Ball سنحصل على AbstractMethodError . لذلك جعل طريقة التقصير حل كل المشاكل.


كما هو موضح في this المقالة ،

دروس الملخص مقابل الواجهات في Java 8

بعد إدخال الأسلوب الافتراضي ، يبدو أن الطبقات البينية والفارغية هي نفسها. ومع ذلك ، فهي لا تزال مفهومًا مختلفًا في Java 8.

يمكن للفئة الملخص تحديد منشئ. هم أكثر تنظيما ويمكن أن يكون لهم دولة مرتبطة بها. بينما في المقابل ، لا يمكن تنفيذ الطريقة الافتراضية إلا من حيث استدعاء أساليب الواجهة الأخرى ، دون الإشارة إلى حالة تطبيق معين. ومن ثم ، يستخدم كلاهما لأغراض مختلفة والاختيار بين اثنين يعتمدان بالفعل على سياق السيناريو.


بخصوص استفسارك من

لذا متى يجب استخدام الواجهة بالطرق الافتراضية ومتى يجب استخدام فئة تجريدية؟ هل ما زالت الطبقات المجردة مفيدة في هذا السيناريو؟

يوفر documentation جافا إجابة مثالية.

فئات الملخص مقارنة بالواجهات:

الطبقات المجردة تشبه الواجهات. لا يمكنك إنشاء مثيل لها ، وقد تحتوي على مزيج من الطرق المعلنة مع أو بدون تنفيذ.

ومع ذلك ، فمع الفئات المجردة ، يمكنك الإعلان عن الحقول غير الثابتة والنهائية ، وتحديد طرق ملموسة عامة ومحمية وخاصية.

مع الواجهات ، تكون جميع الحقول عامة بشكل عام وثابت ونهائي ، وتكون كافة الطرق التي تقوم بتعريفها أو تعريفها (كطرق افتراضية) عامة. بالإضافة إلى ذلك ، يمكنك توسيع فئة واحدة فقط ، سواء كانت مجردة أو غير مجردة ، في حين يمكنك تنفيذ أي عدد من الواجهات.

وقد تم شرح حالات الاستخدام لكل منها أدناه:

ما الفرق بين الواجهة والفئة المجردة؟

هل ما زالت الطبقات المجردة مفيدة في هذا السيناريو؟

نعم فعلا. ما زالت مفيدة. يمكن أن تحتوي على أساليب وسمات غير ثابتة وغير نهائية ( محمية ، خاصة بالإضافة إلى عامة ) ، وهو أمر غير ممكن حتى مع واجهات Java-8.


يتم وصف هذا في هذه article . فكر في forEach من المجموعات.

List<?> list = …
list.forEach(…);

لم يتم التصريح عن forEach بواسطة java.util.List ولا واجهة java.util.Collection بعد. سيكون أحد الحلول الواضحة هو إضافة الطريقة الجديدة إلى الواجهة الحالية وتوفير التنفيذ عند الحاجة في JDK. ومع ذلك ، بمجرد نشر ، فمن المستحيل إضافة أساليب إلى واجهة دون كسر التنفيذ الحالي.

الفائدة التي تجلبها الطرق الافتراضية هي أنه من الممكن الآن إضافة طريقة افتراضية جديدة للواجهة ولا تؤدي إلى تعطيل التطبيقات.


متى يجب استخدام الواجهة بالطرق الافتراضية ومتى يجب استخدام فئة تجريدية؟

التوافق مع الإصدارات السابقة: تخيل أن الواجهة الخاصة بك يتم تنفيذها من خلال مئات الفئات ، وسيؤدي تعديل هذه الواجهة إلى إجبار جميع المستخدمين على تطبيق الطريقة المضافة حديثًا ، على الرغم من أنه قد لا يكون ضروريًا للعديد من الطبقات الأخرى التي تقوم بتطبيق الواجهة ، بالإضافة إلى أنه يتيح لك الواجهة لتكون واجهة وظيفية

حقائق وقيود:

1-يجوز فقط أن يتم الإعلان عنها ضمن واجهة وليس ضمن فئة أو فئة مجردة.

2 - يجب أن توفر الجسم

3-لا يفترض أن تكون مجردة مثل الطرق العادية الأخرى المستخدمة في واجهة.


لماذا يتعين علينا استخدام فئة مجردة:

  1. يمكن أن يكون للفصل التجريدي طرق مجردة وغير مجردة.
  2. لا يدعم الصف الملخص التجليدي الميراث المتعدد.
  3. يمكن أن تحتوي الطبقة المجردة على متغيرات نهائية وغير نهائية ومستقرة وغير ثابتة.
  4. الطبقة المجردة يمكن أن يكون لها أساليب ثابتة ، والطريقة الرئيسية والمنشئ.
  5. الطبقة المجردة يمكن أن توفر تنفيذ واجهة.
  6. يتم استخدام الكلمة الأساسية المجردة لإعلان الطبقة المجردة.

لماذا يتعين علينا استخدام الواجهة:

  1. الواجهة هي المستوى الأكثر تجريدًا لتصميم تطبيقك
  2. واجهة تدعم الميراث متعددة.
  3. واجهة خلق فقط لوصف التوقيعات للفئات الفرعية
  4. واجهة لديها فقط المتغيرات الثابتة والنهائية.
  5. استخدم الطريقة الافتراضية فقط لتوسيع بعض الواجهات ، على سبيل المثال lib. ولكن في الغالب انها ليست ممارسة جيدة :)

@ narendra-pathai: يرجى التفكير أولا من مبدأ مفتوح / مغلق. الأساليب الافتراضية في واجهات فعل ذلك VIOLATE. هذه ميزة سيئة في Java. يشجع التصميم السيئ والعمارة السيئة وانخفاض جودة البرمجيات. أود أن اقترح تجنب استخدام الأساليب الافتراضية تماما.

اسأل نفسك بعض الأسئلة: - لماذا لا يمكنك وضع أساليبك على الطبقة المجردة؟ هل ستحتاج بعد ذلك إلى أكثر من فصل دراسي واحد؟ ثم فكر في ما هو المسؤول عن صفك. هل أنت متأكد من أن جميع الطرق التي ستضعها لفئة واحدة تحقق نفس الغرض؟ قد تكون تميز بين عدة أغراض ثم تقسم صفك إلى عدة صفوف ، لكل غرض صفه الخاص.







default-method