Inheritance In OOP In Dart

✅ ما هي الوراثة؟

الوراثة تعني أن كلاس (فئة) يمكن أن يرث خصائص ودوال من كلاس آخر.

  • الكلاس الأساسي يُسمى: Super Class / Parent Class / Base Class
  • الكلاس الذي يرث يُسمى: Sub Class / Child Class / Derived Class

الوراثة تساعدك على إعادة استخدام الكود وتجنب التكرار.

✳️ أنواع الوراثة في Dart:
النوعالتعريف
1. Single Inheritanceكلاس يرث من كلاس واحد فقط
2. Multi-Level Inheritanceكلاس يرث من كلاس، والذي يرث بدوره من كلاس آخر
3. Hierarchical Inheritanceعدة كائنات ترث من نفس الكلاس الأب
🔹 1. Single Inheritance (وراثة مفردة)
🧠 التعريف:

كلاس واحد يرث من كلاس واحد فقط.

✅ المثال:
class User {
  void login() {
    print('👤 المستخدم قام بتسجيل الدخول');
  }
}

class Admin extends User {
  void manageUsers() {
    print('🛠️ المدير يتحكم بالمستخدمين');
  }
}

void main() {
  Admin admin = Admin();
  admin.login();        // من الكلاس الأب User
  admin.manageUsers();  // من الكلاس الابن Admin
}
Dart
✅ الشرح:
السطرالمعنى
User extends AdminDog يرث جميع خصائص ودوال Animal
admin.login();تم استدعاء دالة من الكلاس الأب
admin.manageUsers();دالة خاصة بالكلاس الابن
🔹 2. Multi-Level Inheritance (وراثة متعددة المستويات)
🧠 التعريف:

كلاس يرث من كلاس، وهذا الكلاس يرث من كلاس آخر.

✅ المثال:
class Person {
  void breathe() {
    print('🌬️ الشخص يتنفس');
  }
}

class Employee extends Person {
  void work() {
    print('💼 الموظف يعمل');
  }
}

class Manager extends Employee {
  void manage() {
    print('📊 المدير يدير الفريق');
  }
}

void main() {
  Manager m = Manager();
  m.breathe(); // من Person
  m.work();    // من Employee
  m.manage();  // من Manager
}
Dart
✅ الشرح:
الكلاسيرث من
EmployeePerson
ManagerEmployee
🔹 3. Hierarchical Inheritance (وراثة هرمية)
🧠 التعريف:

عدة كلاسات ترث من نفس الكلاس الأب.

✅ المثال:
class Vehicle {
  void drive() {
    print('🚗 المركبة تتحرك');
  }
}

class Car extends Vehicle {
  void honk() {
    print('📢 السيارة تطلق البوق');
  }
}

class Truck extends Vehicle {
  void loadCargo() {
    print('🚚 الشاحنة تحمل البضائع');
  }
}

void main() {
  Car car = Car();
  car.drive();  // من Vehicle
  car.honk();   // من Car

  Truck truck = Truck();
  truck.drive();     // من Vehicle
  truck.loadCargo(); // من Truck
}
Dart
شرح الهيكل:

Truck: يرث من Vehicle ويضيف خاصية loadCargo().

Vehicle: الكلاس الأساسي يمثل مركبة عامة.

Car: يرث من Vehicle ويضيف خاصية honk().

💡 ملاحظات مهمة:
ملاحظةDart تقول
Dart لا تدعم الوراثة المتعددة مباشرةأي لا يمكنك أن تكتب: class C extends A, B
استخدم mixin لو كنت تحتاج خصائص من أكثر من كلاسسيتم شرحه لاحقًا إن أردت
يمكنك استخدام super داخل الكلاس الابن لاستدعاء دوال الأبسنشرحها لاحقًا أيضًا
✅ خلاصة الفرق بين الأنواع الثلاثة:
النوععدد الكلاسات التي ترثالمسار
Singleكلاس واحد يرث من واحدChild → Parent
Multi-Levelكل كلاس يرث من الذي قبلهC → B → A
Hierarchicalأكثر من كلاس يرثون من نفس الكلاسDog → Animal ← Cat
🎯 الفكرة: إدارة مدرسة بسيطة
📦 الكلاسات:
الكلاسالنوعيشرح
Personأساسييمثل أي شخص
StudentHierarchicalيرث من Person
TeacherHierarchicalيرث من Person
AdminMulti-Levelيرث من Teacher
ManagerSingleيرث من Admin
✅ الكود الكامل:
// الكلاس الأساسي
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  void displayInfo() {
    print('👤 الاسم: $name - العمر: $age');
  }
}

// وراثة هرمية
class Student extends Person {
  String major;

  Student(String name, int age, this.major) : super(name, age);

  void study() {
    print('📚 $name يدرس تخصص $major');
  }
}

class Teacher extends Person {
  String subject;

  Teacher(String name, int age, this.subject) : super(name, age);

  void teach() {
    print('🧑‍🏫 $name يُدرس مادة $subject');
  }
}

// وراثة متعددة المستويات
class Admin extends Teacher {
  String position;

  Admin(String name, int age, String subject, this.position)
      : super(name, age, subject);

  void manageSystem() {
    print('🛠️ $name (وظيفته: $position) يدير النظام');
  }
}

// وراثة مفردة (Single Inheritance)
class Manager extends Admin {
  Manager(String name, int age, String subject, String position)
      : super(name, age, subject, position);

  void makeDecision() {
    print('📢 $name يتخذ قرارات إدارية عليا');
  }
}

void main() {
  // كائن طالب
  Student s = Student('ياسين', 20, 'علوم حاسب');
  s.displayInfo();
  s.study();

  print('----------');

  // كائن مدرس
  Teacher t = Teacher('ليلى', 35, 'رياضيات');
  t.displayInfo();
  t.teach();

  print('----------');

  // كائن إداري
  Admin a = Admin('خالد', 40, 'فيزياء', 'مدير النظام');
  a.displayInfo();
  a.teach();
  a.manageSystem();

  print('----------');

  // كائن مدير أعلى
  Manager m = Manager('سعاد', 45, 'إدارة أعمال', 'مدير عام');
  m.displayInfo();
  m.teach();
  m.manageSystem();
  m.makeDecision();
}
Dart
✅ النتائج المتوقعة:
👤 الاسم: ياسين - العمر: 20
📚 ياسين يدرس تخصص علوم حاسب
----------
👤 الاسم: ليلى - العمر: 35
🧑‍🏫 ليلى يُدرس مادة رياضيات
----------
👤 الاسم: خالد - العمر: 40
🧑‍🏫 خالد يُدرس مادة فيزياء
🛠️ خالد (وظيفته: مدير النظام) يدير النظام
----------
👤 الاسم: سعاد - العمر: 45
🧑‍🏫 سعاد يُدرس مادة إدارة أعمال
🛠️ سعاد (وظيفته: مدير عام) يدير النظام
📢 سعاد يتخذ قرارات إدارية عليا
Dart
✅ ماذا تعلمت هنا:
المفهومالتطبيق في الكود
Single InheritanceManager يرث من Admin
Multi-LevelManager → Admin → Teacher → Person
HierarchicalStudent و Teacher كلاهما يرث من Person
super(...)استدعاء constructor الأب
إعادة استخدام الوظائفdisplayInfo() موجود في Person ويُستخدم في كل الأبناء
super في Dart
✅ ما هي super؟

كلمة super تُستخدم في الكلاس الابن للإشارة إلى:

  • دوال أو خصائص الكلاس الأب
  • أو لاستدعاء الباني (constructor) للكلاس الأب
🎯 لماذا نستخدم super؟

لأن الكلاس الابن يرث من الأب، وقد نحتاج:

  1. ✅ استدعاء دالة موجودة في الأب (مثل displayInfo)
  2. ✅ الوصول إلى خصائص الكلاس الأب
  3. ✅ تنفيذ constructor الأب لتهيئة البيانات
🔸 أولًا: استخدام super لاستدعاء الدالة من الأب
✅ المثال:
class Person {
  void greet() {
    print('👋 مرحبًا من Person');
  }
}

class Student extends Person {
  void greet() {
    super.greet(); // استدعاء دالة الأب أولًا
    print('🎓 مرحبًا من Student');
  }
}

void main() {
  Student s = Student();
  s.greet();
}
Dart
✅ الناتج:
👋 مرحبًا من Person
🎓 مرحبًا من Student
Dart
✅ الشرح:
السطرما يحدث
super.greet()استدعاء دالة greet() من الكلاس الأب Person
print(...)ثم تنفيذ الدالة الخاصة بالابن
🔸 ثانيًا: استخدام super لاستدعاء Constructor الأب
✅ المثال:
class Person {
  String name;

  Person(this.name) {
    print('✅ تم إنشاء Person: $name');
  }
}

class Teacher extends Person {
  String subject;

  Teacher(String name, this.subject) : super(name) {
    print('👩‍🏫 تم إنشاء Teacher: $subject');
  }
}

void main() {
  Teacher t = Teacher('ليلى', 'رياضيات');
}
Dart

✅ الناتج:

✅ تم إنشاء Person: ليلى
👩‍🏫 تم إنشاء Teacher: رياضيات
Dart
✅ الشرح:
  • super(name) في constructor Teacher تستدعي constructor Person.
  • هذا يهيئ خاصية name من الأب.
🔸 ثالثًا: استخدام super للوصول إلى خصائص الأب
✅ المثال:
class Animal {
  String type = 'حيوان';
}

class Dog extends Animal {
  void showType() {
    print('النوع: ${super.type}');
  }
}

void main() {
  Dog d = Dog();
  d.showType(); // النوع: حيوان
}
Dart
✅ متى تستخدم super؟
الحالةهل تحتاج super؟
تريد تنفيذ دالة من الأب في دالة override✅ نعم
تريد استدعاء constructor الأب✅ نعم
تريد الوصول إلى خاصية في الأب لها نفس اسم خاصية في الابن✅ نعم
تريد فقط استخدام خاصية موروثة❌ لا تحتاج super، يمكن الوصول مباشرة
🧠 ملاحظة مهمة:

إذا لم تقم باستدعاء super(...) في constructor الابن،
Dart تحاول استدعاء constructor الافتراضي للأب.
ولو لم يكن موجودًا، سيحدث خطأ.