دروس الوحدة (2/2)
تعدد الأشكال والطبقات المجردة
يعد تعدد الأشكال والفئات المجردة مفاهيم برمجة موجهة للكائنات متقدمة تسمح لنا بكتابة تعليمات برمجية مرنة وقابلة للتوسيع بشكل مستقل عن تطبيقات محددة.
تعدد الأشكال
يشير مصطلح تعدد الأشكال (أشكال متعددة) إلى القدرة على التعامل مع كائنات من فئات مختلفة كما لو أنها تنتمي إلى نوع شائع. في Java، يمكن للمتغير المرجعي للفئة الفائقة تخزين مرجع لكائن من أي من فئاته الفرعية.
class Animal {
public void makeSound() {
System.out.println("Verso...");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Miao");
}
}بفضل تعدد الأشكال، يمكننا القيام بذلك:
Animal myAnimal1 = new Dog(); // Polymorphism
Animal myAnimal2 = new Cat(); // Polymorphism
myAnimal1.makeSound(); // Executes Dog's method (Woof)
myAnimal2.makeSound(); // Executes Cat's method (Miao)يتم اتخاذ القرار بشأن الطريقة التي سيتم استدعاؤها في وقت التشغيل (الربط المتأخر أو الإرسال الديناميكي) استنادًا إلى الكائن الفعلي، وليس نوع المتغير المرجعي.
فئات الملخصات (abstract)
فئة مجردة هي فئة تم وضع علامة عليها بالكلمة الأساسية abstract التي لا يمكن إنشاء مثيل لها مباشرة (لا يمكنك القيام بـ new MyAbstractClass()). إنه بمثابة "قالب جزئي" للفئات الأخرى.
طرق مجردة
يمكن أن تحتوي الفئة المجردة على طرق مجردة: طرق مُعلنة بدون نص (بدون أقواس متعرجة ولا تعليمات برمجية)، وتنتهي بفاصلة منقوطة. الفئات الفرعية غير المجردة مطلوبة لتنفيذ جميع الأساليب المجردة الموروثة.
abstract class Shape {
String color;
// Abstract method (no body)
public abstract double getArea();
}
class Circle extends Shape {
double radius;
public Circle(double radius) {
this.radius = radius;
}
// Required to implement getArea
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}الربط الديناميكي / الربط المتأخر
كيف تعرف Java الطريقة التي سيتم تنفيذها في وقت التشغيل؟ تُعرف هذه العملية باسم الربط المتأخر (أو الربط الديناميكي). على عكس التحميل الزائد (الذي يتم حله في وقت الترجمة)، لا يعرف المترجم الطريقة المحددة التي سيتم تنفيذها. بدلاً من ذلك، يقوم بإنشاء تعليمات استدعاء عامة. في وقت التشغيل، يقوم Java Virtual Machine (JVM) بفحص الكائن الفعلي في الذاكرة ويستدعي تنفيذ الطريقة المحددة في فئة هذا الكائن.
فئات مجردة والتنفيذ المفقود
إذا ورثت فئة فرعية من فئة مجردة، فلها خياران:
- تنفيذ جميع الأساليب المجردة: في هذه الحالة، يمكن للفئة الفرعية أن تكون فئة عادية (ملموسة) ويمكن إنشاء مثيل لها.
- ** أعلن عن نفسه مجردًا **: إذا كانت الفئة الفرعية لا توفر تطبيقًا لجميع الأساليب المجردة الموروثة، فيجب أيضًا الإعلان عنها باستخدام الكلمة الأساسية
abstract.
abstract class Animal {
public abstract void makeSound();
}
// This class MUST be abstract because it does not implement makeSound()
abstract class Canine extends Animal {
// Inherits makeSound() but does not implement it
}جربه بنفسك
قم بتعريف متغير s من النوع Shape وقم بتعيين كائن دائرة جديد له باستخدام تعدد الأشكال.
إظهار التلميح
اكتب `Shape s = new Circle();` لاستخدام النوع الأساسي كنوع مرجعي.
الحل متاح بعد 3 من المحاولات
اجعل فئة الشكل مجردة وأضف الطريقة المجردة getArea () المزدوجة. ثم أكمل المربع بحيث يقوم بتوسيع الشكل وتنفيذ الجانب العائد لـ getArea() * Side.
إظهار التلميح
قم بتعريف `getArea() الملخص العام المزدوج;` في الشكل. في المربع، أضف `@Override public double getArea() { return Side * Side; }`.
الحل متاح بعد 3 من المحاولات
أعلن في الطريقة الرئيسية عن مصفوفة من النوع Shape[] تحتوي على كائن دائرة بنصف قطر 2.0 وكائن مربع بضلع 3.0. ثم استخدم حلقة (لأو لكل منهما) لطباعة مساحة كل شكل عن طريق استدعاء طريقة getArea().
إظهار التلميح
قم بتعريف المصفوفة باستخدام `Shape[] Shapes = { new Circle(2.0), new Square(3.0) };` ثم قم بالتكرار من خلالها باستخدام طباعة `s.getArea()` لـ (Shape s : الأشكال)`.
الحل متاح بعد 3 من المحاولات