✅ ما هي الوراثة؟
الوراثة تعني أن كلاس (فئة) يمكن أن يرث خصائص ودوال من كلاس آخر.
- الكلاس الأساسي يُسمى: 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 Admin | Dog يرث جميع خصائص ودوال 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✅ الشرح:
الكلاس | يرث من |
---|---|
Employee | Person |
Manager | Employee |
🔹 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 | أساسي | يمثل أي شخص |
Student | Hierarchical | يرث من Person |
Teacher | Hierarchical | يرث من Person |
Admin | Multi-Level | يرث من Teacher |
Manager | Single | يرث من 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 Inheritance | Manager يرث من Admin |
Multi-Level | Manager → Admin → Teacher → Person |
Hierarchical | Student و Teacher كلاهما يرث من Person |
super(...) | استدعاء constructor الأب |
إعادة استخدام الوظائف | displayInfo() موجود في Person ويُستخدم في كل الأبناء |
super
في Dart
✅ ما هي super
؟
كلمة super
تُستخدم في الكلاس الابن للإشارة إلى:
- دوال أو خصائص الكلاس الأب
- أو لاستدعاء الباني (constructor) للكلاس الأب
🎯 لماذا نستخدم super
؟
لأن الكلاس الابن يرث من الأب، وقد نحتاج:
- ✅ استدعاء دالة موجودة في الأب (مثل
displayInfo
) - ✅ الوصول إلى خصائص الكلاس الأب
- ✅ تنفيذ 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)
في constructorTeacher
تستدعي constructorPerson
.- هذا يهيئ خاصية
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 الافتراضي للأب.
ولو لم يكن موجودًا، سيحدث خطأ.