التنفيذ مقابل التوسيع
جزء من قسم البرمجة كائنية التوجه في رحلة Dart على Coddy. الدرس 47 من 110.
الآن بعد أن فهمت كلًا من extends وimplements، لنوضّح متى تستخدم كلًّا منهما.
استخدم extends عندما تريد توريث السلوك. يحصل الصنف الفرعي على كل شيفرة الصنف الأب مجانًا، ويمكنه البناء عليها:
class Animal {
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
void bark() {
print('Woof!');
}
}
void main() {
var dog = Dog();
dog.breathe(); // موروث - يعمل تلقائيًا
dog.bark();
}استخدم implements عندما تريد ضمان بنية من دون توريث الشيفرة. must أن تكتب كل أسلوب بنفسك:
class Robot implements Animal {
@override
void breathe() {
print('Ventilating circuits...'); // تنفيذ مخصص بالكامل
}
}الفرق الرئيسي: تقول extends «أنا نوع من هذا»، بينما تقول implements «يمكنني القيام بما يفعله هذا». إن Dog هو Animal ويتنفس بالطريقة نفسها. إن Robot ليس حيوانًا، لكنه يستطيع الوفاء بالعقد نفسه بمنطقه الخاص.
تذكّر: يمكنك توسيع فئة واحدة فقط، لكن يمكنك تنفيذ العديد من الواجهات. اختر extends لعلاقات الوراثة الحقيقية، وimplements عندما تحتاج إلى المرونة أو تريد فرض عقد دون مشاركة تفاصيل التنفيذ.
التحدي
سهللنبنِ نظامًا للعمال يوضّح متى نستخدم extends بدلًا من implements. ستنشئ فئة عامل أساسية، ثم تعرض النهجين معًا: فئة تُعدّ حقًا "is a" عاملًا وترث السلوك، وفئة أخرى "can do" ما يفعله العامل، ولكن بمنطق custom بالكامل.
ستنظّم الكود في ملفين:
worker.dart: عرّف تسلسل فئات العمال هنا:- فئة
Workerتحتوي على خاصيةString nameومنشئ. أضف طريقةwork()تطبع[name] is working...وطريقةtakeBreak()تطبع[name] takes a coffee break - فئة
OfficeWorkerالتي extends الفئةWorker. أضف خاصيةString department. أعد تعريفwork()لتطبع[name] is typing reports in [department]، مع الإبقاء على سلوكtakeBreak()الموروث - فئة
RobotWorkerالتي implements الفئةWorker. أضف خاصيةString model. بما أن الروبوتات ليست عمالًا فعليًا، لكنها تستطيع القيام بما يفعله العمال، فوفّر implementations custom بالكامل: يجب أن تطبعwork()العبارةRobot [model] is assembling parts، ويجب أن تطبعtakeBreak()العبارةRobot [model] is recharging
- فئة
main.dart: استورد ملف العامل واعرض النهجين:- أنشئ
OfficeWorkerباسم'Alice'في قسم'Marketing' - أنشئ
RobotWorkerبطراز'RX-7' - بالنسبة إلى العامل المكتبي، استدعِ
work()ثمtakeBreak() - اطبع سطرًا فارغًا
- بالنسبة إلى العامل الروبوت، استدعِ
work()ثمtakeBreak()
- أنشئ
لاحظ كيف ترث OfficeWorker الدالة takeBreak() automatically لأنها تمتد من Worker — فهي "is a" عامل حقًا. في المقابل، يجب على RobotWorker توفير implementation خاص به لكل شيء لأنه يطبّق الواجهة فقط — فهو "can do" ما يفعله العامل، ولكن بطريقته الروبوتية الخاصة.
الناتج المتوقع:
Alice is typing reports in Marketing
Alice takes a coffee break
Robot RX-7 is assembling parts
Robot RX-7 is rechargingجرّب بنفسك
import 'worker.dart';
void main() {
// TODO: أنشئ OfficeWorker باسم 'Alice' في قسم 'Marketing'
// TODO: أنشئ RobotWorker بالطراز 'RX-7'
// TODO: بالنسبة للعامل المكتبي، استدعِ work() ثم takeBreak()
// TODO: اطبع سطرًا فارغًا
// TODO: بالنسبة للعامل الروبوت، استدعِ work() ثم takeBreak()
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةالمكتبات والـ Importsمقدمة في الـ OOPالـ Classes مقابل الـ Objectsالكلمة المفتاحية thisالـ Methodsمتغيرات الـ Instanceأساسيات الـ Constructorمراجعة - آلة حاسبة بسيطة4أمان الـ Null
مقدمة في أمان الـ NullNullable مقابل Non-Nullableعاملا الـ ? و !الكلمة المفتاحية Late وأمان الـ Nullالعوامل المدركة للـ Nullأمان الـ Null في الـ Classesمراجعة - نظام ملف تعريف المستخدم7الفئات المجردة والواجهات
الفئات المجردةالدوال المجردةالواجهات في Dartالواجهات الضمنيةالتنفيذ مقابل التوسيعالواجهات المتعددةمراجعة - حاسبة الأشكال10المجموعات والأنماط العامة
نظرة عامة على List و Set و Mapالمجموعات آمنة النوعالفئات العامةالدوال العامةقيود الأنماط العامةIterable و Iteratorملخص - التخزين العام13مفاهيم OOP المتقدمة
التركيب مقابل الوراثة (Composition vs Inheritance)دوال التوسعة (Extension Methods)الأصناف القابلة للاستدعاء (Callable Classes)الأصناف المختومة (Sealed Classes - Dart 3)السجلات (Records - Dart 3)الأنماط والمطابقة (Patterns & Matching - 3.0)التعدادات مع الدوال (Enums with Methods)2المنشئات في Dart
المنشئ الافتراضيالمنشئات المسماةقوائم التهيئةالمنشئات الثابتةالمنشئات المصنعيةالمنشئات الموجهةملخص - بناء الأشكال5التغليف (Encapsulation)
الأعضاء العامة مقابل الخاصةاتفاقية البادئة _الخصوصية على مستوى المكتبةتعمق في Getters و Settersإخفاء المعلوماتمراجعة - سجلات الطلاب8Mixins
مقدمة إلى Mixinsإنشاء Mixinsاستخدام Mixins متعددةالكلمة المفتاحية on في MixinsMixin مقابل الوراثة (Inheritance)Mixin مقابل الواجهة (Interface)مراجعة - نظام الحيوانات (Animal System)3خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticحقول Final و Constمتغيرات Lateالـ Static Methods والحقولدوال الـ Getters والـ Settersمراجعة - مدير الحساب البنكي6الوراثة
أساسيات الوراثةالكلمة المفتاحية superإعادة تعريف الدوال (Method Overriding)الوسم @overrideالكلمة المفتاحية final Classالدوال البانية والوراثةمراجعة - هيكلية الموظفين9تعدد الأشكال
أساسيات تعدد الأشكالتعدد الأشكال عبر الـ Interfacesالتحقق من النوع أثناء التشغيلالمعاملات is و asالكلمة المفتاحية Covariantملخص - معالج الدفع12البرمجة الكائنية غير المتزامنة (Async OOP)
Futures و async/awaitأساسيات الـ Streamsمتحكمات الـ Streamsالـ Constructors غير المتزامنةالعمليات غير المتزامنة في دوال الكلاسمراجعة - جالب البيانات (Data Fetcher)15أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودعتدرّب بنفسك: مترجم Dart عبر الإنترنت