JavaRush /مدونة جافا /Random-AR /الطرق الافتراضية في الواجهات

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

نشرت في المجموعة
يختلف كل إصدار جديد من Java عن الإصدارات السابقة. فيما يلي مثال للتغييرات من المواد التي قمنا بتغطيتها: قبل Java 5، لم تكن هناك حرف enum's' في اللغة.
الطرق الافتراضية في الواجهات - 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("Газ!");
   }

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}


public class Truck implements Car {

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

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}


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

   @Override
   public void brake() {
       System.out.println("Тормоз!");
   }
}
ما رأيك هي المشكلة الرئيسية في هذا الرمز؟ ربما لاحظت أننا كتبنا مجموعة من نفس الكود! هذه المشكلة شائعة في البرمجة ويجب تجنبها. شيء آخر هو أنه قبل إصدار Java 8 لم تكن هناك خيارات حلول خاصة. عندما صدر هذا الإصدار، أصبح من الممكن تحديد الطرق الافتراضية وتنفيذها مباشرة داخل الواجهة! وإليك كيف يتم ذلك:
public interface Car {

   public default void gas() {
       System.out.println("Газ!");
   }

   public default void brake() {
       System.out.println("Тормоз!");
   }
}

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("Эта машина газует по-другому!");
   }

   @Override
   public void brake() {
       System.out.println("Эта машина тормозит по-другому!");
   }
}
ستنفذ جميع أنواع الآلات الـ 99 الأخرى الطريقة الافتراضية، UnusualCarولن يفسد الفصل - الاستثناء - الصورة العامة وسيحدد سلوكها بهدوء. الوراثة المتعددة في الواجهات كما تعلم، لا يوجد وراثة متعددة في Java. وأسباب ذلك كثيرة، سنتناولها بالتفصيل في محاضرة منفصلة. وفي اللغات الأخرى، على سبيل المثال، في لغة C++، يكون الأمر على العكس من ذلك. بدون وراثة متعددة، تنشأ مشكلة خطيرة: يمكن أن يكون للكائن نفسه عدد من الخصائص و"السلوكيات" المختلفة. مثال من الحياة: بالنسبة لوالدينا نحن أطفال، بالنسبة للمعلمين نحن طلاب، بالنسبة للأطباء نحن مرضى. في الحياة، نظهر في أدوار مختلفة، وبالتالي نتصرف بشكل مختلف: من الواضح أننا سنتحدث مع المعلمين بشكل مختلف عن الأصدقاء المقربين. دعونا نحاول ترجمة هذا الموقف إلى كود. لنتخيل أن لدينا فئتين: البركة والقفص. بالنسبة للبركة تحتاج إلى طيور سباحة، وبالنسبة للقفص تحتاج إلى طيور طائرة. للقيام بذلك، قمنا بإنشاء فئتين أساسيتين - FlyingBirdو Waterfowl.
public class Waterfowl {
}

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

   //методы обоих интерфейсов легко объединяются в одном классе

   @Override
   public void fly() {
       System.out.println("Летим!");
   }

   @Override
   public void swim() {

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