تعدد الأشكال
تعدد الأشكال (Polymorphism) يعني "أشكال متعددة". يسمح لك بتنفيذ سلوكيات مختلفة لنفس الواجهة.
مفهوم تعدد الأشكال
| المفهوم | الوصف |
|---|---|
| تعدد الأشكال | نفس الاسم، سلوكيات مختلفة |
| النوع المرجعي | نوع المتغير (الفئة الأصلية) |
| النوع الفعلي | نوع الكائن الحقيقي (الفئة الفرعية) |
مثال أساسي
JAVA
public class Animal {
public void makeSound() {
System.out.println("صوت عام");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("ووف ووف!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("موو!");
}
}
// الاستخدام
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.makeSound(); // ووف ووف!
animal2.makeSound(); // موو!
تعدد الأشكال مع المصفوفات
JAVA
Animal[] animals = {
new Dog("ريكس", 3، "جيرمن"),
new Cat("لوسي", 2، true),
new Dog("بودي", 5، "لابرادور")
};
for (Animal animal : animals) {
animal.makeSound(); // كل حيوان يصدر صوته المختلف
}
تعدد الأشكال مع المعلمات
JAVA
public class AnimalShelter {
public void careFor(Animal animal) {
System.out.println("العناية بـ: " + animal.getName());
animal.eat();
animal.makeSound();
}
}
// الاستخدام
AnimalShelter shelter = new AnimalShelter();
shelter.careFor(new Dog("ريكس", 3، "جيرمن"));
shelter.careFor(new Cat("لوسي", 2، true));
Casting — تحويل الأنواع
Upcasting (تلقائي)
JAVA
Dog dog = new Dog("ريكس", 3، "جيرمن");
Animal animal = dog; // تلقائي — Dog هو Animal
animal.makeSound(); // ووف ووف!
Downcasting (يدوي)
JAVA
Animal animal = new Dog("ريكس", 3، "جيرمن");
// Dog dog = animal; // ❌ خطأ
Dog dog = (Dog) animal; // ✅ صحيح
dog.bark();
التحقق قبل التحويل
JAVA
Animal animal = new Cat("لوسي", 2، true);
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark();
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.meow();
}
مثال كامل: نظام الدفع
JAVA
public abstract class Payment {
protected double amount;
protected String date;
public Payment(double amount, String date) {
this.amount = amount;
this.date = date;
}
public abstract boolean processPayment();
public abstract String getReceipt();
}
public class CreditCardPayment extends Payment {
private String cardNumber;
public CreditCardPayment(double amount, String date, String cardNumber) {
super(amount, date);
this.cardNumber = cardNumber;
}
@Override
public boolean processPayment() {
System.out.println("معالجة الدفع بالبطاقة: " + cardNumber);
return true;
}
@Override
public String getReceipt() {
return "إيصال بطاقة ائتمان: " + amount + " ريال";
}
}
public class CashPayment extends Payment {
public CashPayment(double amount, String date) {
super(amount, date);
}
@Override
public boolean processPayment() {
System.out.println("معالجة الدفع النقدي");
return true;
}
@Override
public String getReceipt() {
return "إيصال نقدي: " + amount + " ريال";
}
}
// الاستخدام
Payment[] payments = {
new CreditCardPayment(100, "2026-06-25"، "1234-5678"),
new CashPayment(50، "2026-06-25")
};
for (Payment payment : payments) {
payment.processPayment();
System.out.println(payment.getReceipt());
}
❓ أسئلة شائعة
س ما هو Dynamic Dispatch؟
ج هو الآلية التي يختار بها Java الدالة الصحيحة أثناء التشغيل بناءً على نوع الكائن الفعلي.
س لماذا نحتاج Downcasting؟
ج عندما نريد الوصول لدوال خاصة بالفئة الفرعية.
س هل يمكن تجاوز الدوال الثابتة (static)؟
ج لا، الدوال الثابتة لا يمكن تجاوزها لأنها مرتبطة بالفئة وليس بالكائن.
📖 ملخص
- تعدد الأشكال: نفس الاسم، سلوكيات مختلفة
- Upcasting تلقائي، Downcasting يدوي
- instanceof للتحقق قبل التحويل
- Dynamic Dispatch يختار الدالة الصحيحة أثناء التشغيل
📝 تمارين
- حيوانات: أنشئ 5 فئات حيوانات مع سلوكيات مختلفة
- أشكال: أنشئ فئات أشكال مع دوال لحساب المساحة والمحيط
- وظائف: أنشئ فئات وظائف مع رواتب ومكافآت مختلفة
الدرس التالي
في الدرس التالي، سنتعلم الواجهات و Lambda — الواجهات والدوال المجردة.



