Abstract Class هو كلاس لا يمكن إنشاء كائن (object) منه مباشرة، يُستخدم كـ قالب (Template) لكلاسات أخرى ترث منه وتقوم بتنفيذ (تطبيق) ما يلزم من الدوال.
🔹 الهدف منه:
إجبار الكلاسات الأبناء على تطبيق (implement) بعض الدوال.
توفير قاعدة مشتركة من الخصائص والدوال.
✅ الشكل العام:
abstractclassClassName {voidmethod(); // مجردة}
Dart
✅ ملاحظات مهمة:
الخاصية
هل تنطبق؟
❌ لا يمكن إنشاء كائن منه
✅
✅ يمكن أن يحتوي على دوال بدون جسم (abstract)
✅
✅ يمكن أن يحتوي على دوال عادية أيضًا
✅
✅ يمكن أن يحتوي على خصائص
✅
✅ مثال 1: كلاس مجرد يحتوي دوال مجردة فقط
abstractclassEmployee {voidwork(); // دالة مجردة لا تحتوي على جسم}classManagerextendsEmployee {@overridevoidwork() {print("يدير الفريق ويضع الخطط 🗂️"); }}classDeveloperextendsEmployee {@overridevoidwork() {print("يكتب الكود ويطور التطبيقات 💻"); }}voidmain() {Employee e1 =Manager();Employee e2 =Developer(); e1.work(); // يدير الفريق ويضع الخطط 🗂️ e2.work(); // يكتب الكود ويطور التطبيقات 💻}
Dart
✅ شرح المثال:
Employee هو كلاس مجرد abstract class فيه دالة work() بدون جسم.
Manager و Developer ورثوا منه ونفذوا دالة work بطريقتهم.
وقت التنفيذ، كل كائن يعمل بحسب وظيفته.
✅ مثال 2: كلاس مجرد يحتوي خصائص ودوال عادية
abstractclassShape {String color;Shape(this.color);voiddraw(); // مجردةvoidprintColor() {print("لون الشكل هو: $color"); }}classCircleextendsShape {Circle(String color) :super(color);@overridevoiddraw() {print("رسم دائرة"); }}voidmain() {Circle c =Circle("أحمر"); c.draw(); // رسم دائرة c.printColor(); // لون الشكل هو: أحمر}
Dart
✅ الفروقات بين الكلاسات العادية و abstract
الكلاس العادي
الكلاس المجرد
يمكن إنشاء كائن منه
لا يمكن
ليس بالضرورة أن يرث منه أحد
الهدف منه أن يتم توريثه
لا يحتوي على دوال مجردة
قد يحتوي
ليس له قيود على الأبناء
يجبر الأبناء على تنفيذ بعض الدوال
✅ أين نستخدم abstract class؟ (أماكن الاستخدام):
الحالة
الوصف
مثال
🧱 قاعدة عامة
لما يكون عندك خصائص مشتركة بين عدة كائنات
كائنات Animal أو Shape
🧪 نماذج تصميم (Design Patterns)
مثل Template Pattern أو Strategy
تنفيذ متعدد بمرجعية واحدة
🔐 في الأنظمة المعقدة
مثل أنظمة تسجيل الدخول: كل نوع مستخدم يرث من UserBase
AdminUser, NormalUser
📱 في التطبيقات متعددة الواجهات
لفصل شكل العرض عن المنطق
واجهات متعددة تشترك بسلوك
✅ مثال 3: Abstract في نظام دخول المستخدمين
abstractclassUser {String name;User(this.name);voidlogin(); // يجب أن تطبقه كل فئة}classAdminUserextendsUser {AdminUser(String name) :super(name);@overridevoidlogin() {print("الدخول كمدير: $name"); }}classNormalUserextendsUser {NormalUser(String name) :super(name);@overridevoidlogin() {print("الدخول كمستخدم عادي: $name"); }}voidmain() {User u1 =AdminUser("أحمد");User u2 =NormalUser("سارة"); u1.login(); // الدخول كمدير: أحمد u2.login(); // الدخول كمستخدم عادي: سارة}