CodeGym /مدونة جافا /Random-AR /الطرق الافتراضية في الواجهات
John Squirrels
مستوى
San Francisco

الطرق الافتراضية في الواجهات

نشرت في المجموعة
يختلف كل إصدار جديد من Java عن الإصدارات السابقة. فيما يلي مثال على التغييرات في المواد التي قمنا بتغطيتها: قبل Java 5، لم تكن اللغة تحتوي على enums. الطرق الافتراضية في الواجهات - 1وبالمثل، تختلف Java 8 بشكل ملحوظ عن Java 7. تمت كتابة معظم دروسنا للإصدار السابع من اللغة، لكننا بالطبع لن نتجاهل الابتكارات المهمة. وبما أننا نتحدث بالفعل عن الواجهات في هذا الدرس، فسنأخذ في الاعتبار تحديثًا واحدًا - الطرق الافتراضية في الواجهات . أنت تعلم بالفعل أن الواجهة لا تنفذ السلوك . وتتمثل مهمتها في وصف السلوك الذي يجب أن تتمتع به جميع الكائنات التي تنفذه . لكن المطورين واجهوا في كثير من الأحيان مواقف يكون فيها تنفيذ الطريقة هو نفسه في جميع الفئات. لنفكر في مثال سيارتنا القديمة:

public interface Car {

   public void gas();

   public void brake();
}
public class Sedan implements Car {

   @Override
   public void gas() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}


public class Truck implements Car {

   @Override
   public void gas() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}


public class F1Car implements Car {
   @Override
   public void gas() {
       System.out.println("Gas!");
   }

   @Override
   public void brake() {
       System.out.println("Brake!");
   }
}
"برأيك، ما هي المشكلة الرئيسية في هذا الكود؟ ربما لاحظت أننا كتبنا مجموعة من الأكواد المتكررة! هذه المشكلة شائعة في البرمجة، ويجب عليك تجنبها. إنها مسألة أخرى أنه لم تكن هناك حلول معينة من قبل تم إصدار Java 8. مع هذا الإصدار، أصبحت القدرة على تحديد الأساليب الافتراضية وتنفيذها مباشرة داخل الواجهة! وإليك كيفية القيام بذلك:

public interface Car {

   public default void gas() {
       System.out.println("Gas!");
   }

   public default void brake() {
       System.out.println("Brake!");
   }
}

public class Sedan implements Car {

}

public class Truck implements Car {

}

public class F1Car implements Car {

}
والآن تم نقل الأساليب gas()والطرق brake()، التي كانت هي نفسها بالنسبة لجميع السيارات، إلى الواجهة. ليس هناك حاجة إلى رمز متكرر. علاوة على ذلك، فإن الأساليب متوفرة في كل فصل!

public class Main {

   public static void main(String[] args) {

       F1Car f1Car = new F1Car();
       Sedan sedan = new Sedan();
       Truck truck = new Truck();
       truck.gas();
       sedan.gas();
       f1Car.brake();
   }
}
ماذا لو كان هناك 100 فئة تستخدم هذه gas()الطريقة، لكن 99 منها فقط لها نفس السلوك؟ هل هذا يفسد كل شيء ويجعل الطريقة الافتراضية غير صالحة لهذا الموقف؟ بالطبع لا :) يمكن تجاوز الطرق الافتراضية في الواجهات بنفس طريقة الطرق العادية.

public class UnusualCar implements Car {
   @Override
   public void gas() {
       System.out.println("This car accelerates differently!");
   }

   @Override
   public void brake() {
       System.out.println("This car decelerates differently!");
   }
}
جميع أنواع السيارات الـ 99 الأخرى ستطبق الطريقة الافتراضية، والفئة UnusualCar، التي تعتبر استثناءً، لن تفسد الصورة العامة وتحدد سلوكها بهدوء. وراثة متعددة للواجهات. كما تعلم، جافا لا تدعم الوراثة المتعددة. هناك اسباب كثيرة لهذا. سننظر إليهم بالتفصيل في درس منفصل. اللغات الأخرى، مثل C++، تدعمه. بدون وراثة متعددة، تنشأ مشكلة خطيرة: يمكن أن يكون لكائن واحد عدة خصائص و"سلوكيات" مختلفة. إليكم مثال من الحياة: نحن أطفال لآبائنا، وطلاب لمعلمينا، ومرضى لأطبائنا. في الحياة، نتخذ أدوارًا مختلفة، وبالتالي نتصرف بشكل مختلف: من الواضح أننا لن نتحدث مع المعلمين بنفس الطريقة التي نتحدث بها مع أصدقائنا المقربين. دعونا نحاول ترجمة هذا إلى رمز. تخيل أن لدينا فئتين: البركة والقفص. بالنسبة للبركة، نحتاج إلى الطيور المائية؛ بالنسبة للقفص، نحتاج إلى طيور تحلق. للقيام بذلك، قمنا بإنشاء فئتين أساسيتين: FlyingBirdو Waterfowl.

public class Waterfowl {
}

public class FlyingBird {
}
وبناء على ذلك، سوف نرسل الطيور التي ترث فئاتها FlyingBirdإلى القفص، وسنرسل الطيور التي ترث Waterfowlإلى البركة. يبدو كل شيء بسيطًا جدًا. ولكن أين نرسل بطة؟ يسبح ويطير. وليس لدينا ميراث متعدد. ولحسن الحظ، تدعم Java التنفيذ المتعدد للواجهات. على الرغم من أن الفصل لا يمكنه وراثة العديد من الآباء، إلا أنه يمكنه بسهولة تنفيذ عدة واجهات! يمكن أن تكون بطتنا طائرًا طائرًا أو طائرًا مائيًا :) نحتاج ببساطة إلى إنشاء FlyingBirdواجهات Waterfowlبدلاً من الطبقات لتحقيق النتيجة المرجوة.

public class Duck implements FlyingBird, Waterfowl {

   // The methods of both interfaces can be easily combined into one class

   @Override
   public void fly() {
       System.out.println("Fly!");
   }

   @Override
   public void swim() {

       System.out.println("Swim!");
   }
}
وبناءً على ذلك، يحتفظ برنامجنا بمرونة الفئات، وبالاشتراك مع الأساليب الافتراضية، تصبح قدرتنا على تحديد سلوك الكائنات غير محدودة تقريبًا! :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION