إعادة تعريف الدوال (Method Overriding)
جزء من قسم البرمجة كائنية التوجه في رحلة Dart على Coddy. الدرس 38 من 110.
يحدث تجاوز method عندما توفر فئة فرعية تطبيقها الخاص لـ method موجودة بالفعل في الفئة parent. يتيح ذلك للفئات الفرعية تخصيص السلوك الموروث مع الحفاظ على توقيع method نفسه.
عندما تعرّف method في class فرعية بالاسم والمعلمات نفسيهما كما في parent، تتولى نسخة الفئة الابنة المهمة:
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
void speak() {
print('$name barks: Woof!');
}
}
void main() {
var animal = Animal('Generic');
var dog = Dog('Buddy');
animal.speak(); // Generic يصدر صوتًا
dog.speak(); // Buddy ينبح: Woof!
}عندما تستدعي speak() على نسخة من Dog، ينفّذ Dart إصدار Dog، وليس إصدار Animal. لقد أجرت الفئة الابنة override لـ method الخاصة بـ parent.
يمكنك أيضًا الجمع بين إعادة التعريف وsuper لتوسيع سلوك parent بدلًا من استبداله:
class Cat extends Animal {
Cat(String name) : super(name);
void speak() {
super.speak(); // استدعِ نسخة الأب أولاً
print('$name also purrs');
}
}يتيح لك هذا النمط البناء على الوظائف الحالية. القاعدة الأساسية بسيطة: يستبدل method بالاسم والمعلمات نفسيهما تنفيذ الفئة الأصلية عند استدعائه على مثيلات الفئة الفرعية.
التحدي
سهللنبنِ نظام إشعارات يوضّح كيف يمكن لـ child classes إجراء override لأساليب parent لتخصيص السلوك. ستنشئ أنواعًا مختلفة من الإشعارات، يسلّم كل منها الرسائل بطريقته الفريدة.
ستنظّم الكود في ملفين:
notification.dart: Define التسلسل الهرمي للإشعارات هنا:- class
Notification(الـ parent) معString titleوString message. أدرج constructor يأخذ القيمتين وmethodsend()يطبعNotification: [title] - [message] - class
EmailNotificationالتي تمتد منNotificationوتضيف خاصيةString recipient. أجرِ override لـmethodsend()ليطبعSending email to [recipient]: [title] - [message] - class
PushNotificationالتي تمتد منNotificationوتضيف خاصيةString deviceId. أجرِ override لـmethodsend()لاستدعاء method الـparent أولًا باستخدامsuper، ثم طباعةPushed to device: [deviceId]في السطر التالي
- class
main.dart: استورد ملف الإشعارات الخاص بك ووضّح override للـmethod أثناء العمل:- أنشئ Notification أساسيًا بعنوان
'Alert'ورسالة'System update available' - call لـmethod
send()الخاص به - اطبع سطرًا فارغًا
- أنشئ
EmailNotificationبعنوان'Welcome'، ورسالة'Thanks for signing up!'، وrecipient بقيمة'user@example.com' - call لـmethod
send()الخاص به - اطبع سطرًا فارغًا
- أنشئ
PushNotificationبعنوان'Reminder'، ورسالة'Meeting in 10 minutes'، وdeviceId بقيمة'DEVICE-001' - call لـmethod
send()الخاص به
- أنشئ Notification أساسيًا بعنوان
لاحظ كيف تستبدل EmailNotification سلوك الـparent بالكامل، بينما تمدّه PushNotification باستدعاء super.send() أولًا. كلا الأسلوبين طريقتان صحيحتان لإجراء override للـmethods وفقًا لاحتياجاتك.
المخرجات المتوقعة:
Notification: Alert - System update available
Sending email to user@example.com: Welcome - Thanks for signing up!
Notification: Reminder - Meeting in 10 minutes
Pushed to device: DEVICE-001جرّب بنفسك
import 'notification.dart';
void main() {
// TODO: Create a base Notification with title 'Alert' and message 'System update available'
// استدعِ method send() الخاص به
// TODO: اطبع سطراً فارغاً
// TODO: أنشئ EmailNotification مع:
// - title: 'Welcome'
// - message: 'Thanks for signing up!'
// - recipient: 'user@example.com'
// استدعِ method send() الخاص به
// TODO: اطبع سطراً فارغاً
// TODO: أنشئ PushNotification مع:
// - title: 'Reminder'
// - message: 'Meeting in 10 minutes'
// - deviceId: 'DEVICE-001'
// استدعِ method send() الخاص به
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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 عبر الإنترنت