حدود الوراثة العميقة
جزء من قسم Object Oriented Programming في رحلة JavaScript على Coddy — الدرس 48 من 56.
بينما يُعد التوريث مفيداً، فإن إنشاء تسلسلات هرمية عميقة جداً للتوريث (الأب ← الابن ← الحفيد ← ابن الحفيد) يمكن أن يؤدي إلى مشاكل. فكلما زاد عمق السلسلة، أصبح من الصعب فهم الكود وصيانته وتعديله.
دعونا نرى ما يحدث مع سلسلة وراثة عميقة:
// الفئة الأساسية
class Vehicle {
constructor(type) {
this.type = type;
this.isRunning = false;
}
start() {
this.isRunning = true;
console.log(`${this.type} started`);
}
}
// المستوى الأول من الوراثة
class Car extends Vehicle {
constructor(make, model) {
super("Car");
this.make = make;
this.model = model;
this.wheels = 4;
}
honk() {
console.log("Beep beep!");
}
}
// المستوى الثاني من الوراثة
class SportsCar extends Car {
constructor(make, model, topSpeed) {
super(make, model);
this.topSpeed = topSpeed;
}
race() {
this.start();
console.log(`Racing at ${this.topSpeed} mph!`);
}
}في هذا المثال، SportsCar عميقة بمستويين في الوراثة. يمكن أن يؤدي هذا إلى عدة مشاكل:
- قد تؤدي التغييرات في Vehicle إلى كسر SportsCar بشكل غير متوقع
- مع نمو سلسلة الوراثة، يصبح من الصعب تتبع مصدر الأساليب والخصائص
- تُجبر على علاقات "is-a" قد لا تكون مرنة بما يكفي
التحدي
أكمل ملف Robot.js لجعل الروبوت يعمل. في الوقت الحالي، تم بناء الروبوت ولكنه لا يستطيع فعل أي شيء.
ما يجب فعله في <strong>Robot.js</strong>:
- أنشئ مكونات speaker و mover داخل constructor الروبوت
- استخدم المكونات في الدوال (methods):
- في
greet(): استدعِthis.speaker.speak("Hello!"); - في
walkForward(): استدعِthis.mover.move("forward");
- في
لماذا نفعل هذا: هذا ما يسمى التركيب (composition) - حيث يتم بناء الروبوت من خلال دمج مكونات أصغر. الروبوت لديه (has-a) مكبر صوت (للتحدث) و لديه (has-a) محرك (للحركة)، بدلاً من وراثة هذه القدرات.
ورقة مرجعية
يمكن أن تؤدي التسلسلات الهرمية العميقة للوراثة (أب ← ابن ← حفيد) إلى مشاكل في الصيانة وعدم المرونة. فكلما زاد عمق السلسلة، أصبح من الصعب فهم الكود وتعديله.
مثال على سلسلة وراثة عميقة:
class Vehicle {
constructor(type) {
this.type = type;
this.isRunning = false;
}
start() {
this.isRunning = true;
console.log(`${this.type} started`);
}
}
class Car extends Vehicle {
constructor(make, model) {
super("Car");
this.make = make;
this.model = model;
}
}
class SportsCar extends Car {
constructor(make, model, topSpeed) {
super(make, model);
this.topSpeed = topSpeed;
}
}مشاكل الوراثة العميقة:
- يمكن أن تؤدي التغييرات في الفئات الأساسية إلى كسر الفئات التابعة بشكل غير متوقع
- يصعب تتبع مصدر الدوال (methods) والخصائص (properties)
- تفرض علاقات "is-a" جامدة تفتقر إلى المرونة
التركيب (Composition) كبديل: بدلاً من الوراثة، استخدم التركيب حيث تمتلك الكائنات علاقة have-a مع المكونات، من خلال دمج أجزاء أصغر لبناء الوظائف.
جرّب بنفسك
import { Robot } from './Robot.js';
const myRobot = new Robot('Robo');
myRobot.greet(); // يجب أن تكون النتيجة: Saying: "Hello!"
myRobot.walkForward(); // يجب أن تكون النتيجة: Moving forwardيتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1الكائنات والكلمة المفتاحية this
مراجعة سريعة: الكائناتإضافة Methods إلى الكائناتفهم الكلمة المفتاحية thisConstructor Functionsالكلمة المفتاحية newتحدي المراجعة7الوراثة والكلمة المفتاحية extends
الوراثةعلاقة "is-a"الكلمة المفتاحية extendsالدالة super()وراثة الخصائص والوظائفتحدي المراجعة2تنظيم الكود
ما هي الـ Modules؟التصدير باستخدام exportالاستيراد باستخدام importالـ Default مقابل الـ Named Exports8تنظيم كود OOP
تنظيم الـ Classes في Modules11مشروع: مصيّر الأشكال
إعداد: فئة Shape والتصديروراثة فئة Circle