| الكلمة المفتاحية | الوظيفة |
|---|---|
| extends | جعل فئة ترث من فئة أخرى |
| super() | استدعاء constructor الفئة الأب |
| super.method() | استدعاء أسلوب من الفئة الأب |
| Override | إعادة تعريف أسلوب موروث في الفئة الفرعية |
الوراثة تسمح لفئة جديدة (تُسمى الفئة الفرعية أو Subclass) بأن "ترث" كل الخصائص والأساليب من فئة أخرى موجودة (تُسمى الفئة الأساسية أو الأب Superclass)، مع القدرة على إضافة خصائص وأساليب جديدة خاصة بها، أو حتى إعادة تعريف (Override) سلوك موروث لتخصيصه. هذا يُشجّع على إعادة استخدام الكود وتنظيمه بشكل هرمي منطقي.
في جافاسكريبت الحديثة، تُستخدم الكلمة المفتاحية extends لجعل فئة تَرث من فئة أخرى. داخل constructor الفئة الفرعية، يجب استدعاء super() قبل استخدام this بأي شكل — وهذا الاستدعاء يُنفّذ constructor الفئة الأب أولاً لتهيئة الخصائص الموروثة، ثم يمكنك بعده إضافة تهيئة خاصة بالفئة الفرعية.
يمكن أيضاً استخدام super داخل أي أسلوب (وليس فقط constructor) للوصول إلى نسخة الأسلوب المُعرَّفة في الفئة الأب تحديداً، حتى لو أعادت الفئة الفرعية تعريف نفس اسم الأسلوب (Method Overriding) — وهذا مفيد جداً عندما تريد "توسيع" سلوك الأب بدل استبداله بالكامل.
إعادة تعريف الأسلوب (Overriding) تعني أن الفئة الفرعية تُعرِّف أسلوباً بنفس اسم أسلوب موروث من الأب، فيُستخدم تعريف الفئة الفرعية بدلاً من تعريف الأب عند استدعائه على كائن من الفئة الفرعية — هذا هو أساس مبدأ "تعدد الأشكال" (Polymorphism) في البرمجة كائنية التوجه، حيث يمكن لكائنات مختلفة الاستجابة لنفس استدعاء الأسلوب بسلوك مختلف حسب فئتها الفعلية.
| 1 | class حيوان { |
| 2 | constructor(اسم) { |
| 3 | this.اسم = اسم; |
| 4 | } |
| 5 | يصدر_صوتا() { |
| 6 | return `${this.اسم} يصدر صوتاً`; |
| 7 | } |
| 8 | } |
| 9 | |
| 10 | class كلب extends حيوان { |
| 11 | constructor(اسم, سلالة) { |
| 12 | super(اسم); // استدعاء constructor الأب أولاً |
| 13 | this.سلالة = سلالة; |
| 14 | } |
| 15 | يصدر_صوتا() { |
| 16 | return `${this.اسم} ينبح!`; // إعادة تعريف (Override) |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | const ك = new كلب("ريكس", "جيرمن شيبرد"); |
| 21 | console.log(ك.يصدر_صوتا()); // "ريكس ينبح!" |
مثال 1: استخدام super لتوسيع سلوك الأب
| 1 | // توسيع سلوك الأب باستخدام super داخل أسلوب |
| 2 | class موظف { |
| 3 | constructor(اسم, راتب_أساسي) { |
| 4 | this.اسم = اسم; |
| 5 | this.راتب_أساسي = راتب_أساسي; |
| 6 | } |
| 7 | حساب_الراتب() { |
| 8 | return this.راتب_أساسي; |
| 9 | } |
| 10 | } |
| 11 | |
| 12 | class مدير extends موظف { |
| 13 | constructor(اسم, راتب_أساسي, بدل_إدارة) { |
| 14 | super(اسم, راتب_أساسي); |
| 15 | this.بدل_إدارة = بدل_إدارة; |
| 16 | } |
| 17 | حساب_الراتب() { |
| 18 | // نستدعي منطق الأب أولاً، ثم نضيف عليه |
| 19 | return super.حساب_الراتب() + this.بدل_إدارة; |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | const م = new مدير("علي", 8000, 2000); |
| 24 | console.log(م.حساب_الراتب()); // 10000 |
مثال 2: تعدد الأشكال عبر إعادة تعريف الأساليب
| 1 | // تعدد الأشكال (Polymorphism) |
| 2 | class شكل { |
| 3 | المساحة() { return 0; } |
| 4 | } |
| 5 | class دائرة extends شكل { |
| 6 | constructor(نصف_قطر) { super(); this.نصف_قطر = نصف_قطر; } |
| 7 | المساحة() { return Math.PI * this.نصف_قطر ** 2; } |
| 8 | } |
| 9 | class مربع extends شكل { |
| 10 | constructor(ضلع) { super(); this.ضلع = ضلع; } |
| 11 | المساحة() { return this.ضلع ** 2; } |
| 12 | } |
| 13 | |
| 14 | const أشكال = [new دائرة(3), new مربع(4)]; |
| 15 | أشكال.forEach(ش => console.log(ش.المساحة().toFixed(2))); |