انتقل إلى محتوى الدرس
الدرس 113
دورة جافا سكريبت

وراثة الأصناف بـ extends وsuper في JavaScriptJavaScript Class Inheritance

أتقن وراثة الأصناف في JavaScript عبر extends وsuper: هيئ باني الأب بأمان، وخصص الدوال الموروثة ووسعها، وتعرف على حدود الحقول الخاصة وتعدد الأشكال بـ instanceof.
أقسام الدرس
5
الأمثلة
3
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
3,046
محتوى الدرس
في هذا الدرس 5تصفّح المواضيع

عندما تشترك عدة نماذج برمجية في الخصائص والسلوك الأساسي — مثل حساب أساسي Account وحساب احترافي ProAccount — فإن نسخ الحقول والدوال ذاتها في كل صنف يضاعف أخطاء الصيانة. تعالج JavaScript ذلك بأناقة عبر الكلمة المحجوزة extends؛ إذ تنشئ الصيغة class SubClass extends BaseClass صنفاً فرعياً يرث تلقائياً كافة الدوال وخصائص الوصول المعرفة على النموذج الأولي للصنف الأب.

وإذا لم يكتب الصنف الفرعي دالة باني constructor خاصة به، يولّد المحرك تلقائياً بانياً يمرر كافة المعاملات للأب عبر super(...args).

مخطط وراثة الأصناف في JavaScript يوضح ربط النموذج الأولي بـ extends وتهيئة باني الأب بـ super وتوسعة الدوال وفحص الهوية بـ instanceof

متى عرّف الصنف الابن دالة constructor(...) خاصة به، وجب عليه استدعاء super(...) قبل أي قراءة أو كتابة على الكائن this. فالباني المشتق في JavaScript لا يحجز كائن النسخة الفارغ بنفسه، بل يفوض إنشاء النسخة وتهيئة حقول الأب إلى باني الصنف الأب عبر super(...).

أي محاولة لكتابة this.tier = tier قبل سطر super(owner) تطلق فوراً الخطأ الصريح ReferenceError.

JavaScript
class Account {
  constructor(owner) { this.owner = owner; }
  badge() { return `User: ${this.owner}`; }
}
class ProAccount extends Account {
  constructor(owner, tier) { super(owner); this.tier = tier; }
}
const pro = new ProAccount('Nour', 'Gold');
document.getElementById('inh-out').textContent =
  `${pro.badge()} | Tier: ${pro.tier}`;

يستطيع الصنف الفرعي تعريف دالة تحمل نفس اسم دالة الأب من أجل تخصيص سلوكها. وبدلاً من إعادة كتابة كود الأب من الصفر، يمكن للدالة الفرعية استدعاء super.methodName(...) لتنفيذ منطق الأب الأصلي ثم البناء فوق نتيجته:

الصيغة البرمجيةموضع الاستخدامالأثر أثناء التنفيذ
class B extends Aرأس تعريف الصنفيربط B.prototype لتفويض البحث عن الدوال إلى A.prototype
super(arg1, arg2)باني الصنف الابنيشغل باني الأب ويهيئ مرجع النسخة this
super.describe()دالة أو get في الابنيستدعي دالة الأب مرتبطةً بالكائن الابن الحالي this
إحلال كامل بدون superدالة في الصنف الابنيستبدل سلوك الأب بالكامل لنسخ الصنف الفرعي B
JavaScript
class Logger {
  format(msg) { return `[INFO] ${msg}`; }
}
class AuditLogger extends Logger {
  format(msg) {
    return `${super.format(msg)} (verified)`;
  }
}
const log = new AuditLogger();
document.getElementById('sup-out').textContent =
  log.format('Session started');

تخضع الحقول والدوال الخاصة المسبوقة بعلامة # لنطاق معجمي صارم يقتصر على جسم الصنف المصرح عنها فيه فقط؛ فلا يمكن للصنف الفرعي كتابة this.#secret مباشرةً لقراءة حقل خاص يملكه الأب، وإلا أطلق المحرك خطأ صياغة SyntaxError فوري.

وعندما يرغب الصنف الأب في إتاحة قراءة أو تعديل حالته الخاصة للأبناء بضوابط آمنة، يوفر خصائص وصول get وset أو دوال محكومة يرثها الأبناء عبر النموذج الأولي بينما يبقى الحقل الخام محصناً.

يعني تعدد الأشكال أن تشترك الأصناف الفرعية المختلفة في واجهة دالة موحدة — مثل area() أو send() — بينما ينفذ كل صنف معادلته المتخصصة. بذلك يمر الكود المستدعي على العناصر في حلقة نظيفة دون فروع شرطية معقدة، كما يرجع التعبير obj instanceof Parent القيمة true لكل نسخة فرعية على طول سلسلة الوراثة.

في المشاريع العملية يُنصح بإبقاء شجرة الوراثة ضحلة (مستوى أو مستويين) وتفضيل التركيب عندما لا تجمع الأصناف علاقة انتماء حقيقية.

JavaScript
class Shape { area() { return 0; } }
class Square extends Shape {
  constructor(s) { super(); this.s = s; }
  area() { return this.s * this.s; }
}
const sq = new Square(6);
const checks =
  `${sq instanceof Square} / ${sq instanceof Shape}`;
document.getElementById('poly-out').textContent =
  `Area: ${sq.area()} | Square/Shape: ${checks}`;
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

تعلمت في هذا الدرس اشتقاق الأصناف الفرعية بالكلمة extends، وتهيئة باني الأب أولاً عبر super(...)، وتخصيص وتوسعة الدوال الموروثة عبر super.method()، واحترام حدود الحقول الخاصة، وتوظيف تعدد الأشكال وفحص instanceof. الخطوة التالية: انتقل إلى درس «الدوال والخصائص الساكنة في الأصناف» لبناء دوال مساعدة ومصانع إنشاء وحقول مشتركة تابعة للصنف مباشرةً.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Derived Class (extends) الصنف الفرعي المشتق extends
صنف ابن يُعرّف بالكلمة extends ويرث تلقائياً دوال وخصائص النموذج الأولي للصنف الأب.
للمراجعة
02 Super Constructor Call (super()) استدعاء باني الأب super()
استدعاء إلزامي داخل باني الصنف الابن يخصص النسخة ويهيئ خصائص الأب قبل لمس الكائن this.
للمراجعة
03 Method Overriding تخصيص الدالة الموروثة
إعادة تعريف دالة موروثة داخل الصنف الفرعي لتخصيص سلوكها أو البناء فوق نتيجة super.method().
للمراجعة
04 Polymorphism تعدد الأشكال الكائني
استدعاء اسم الدالة الموحد عبر نسخ أصناف فرعية متنوعة بحيث ينفذ كل صنف سلوكه الخاص بمرونة.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات2

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 2 مفهومةأول بطاقة، أول خطوة
01 DRY DRY
Don't Repeat Yourself
مبدأ عدم تكرار الكود، ويتحقق بجمع الخصائص والدوال المشتركة في صنف أب واحد بدلاً من نسخها.
للمراجعة
02 LSP LSP
Liskov Substitution Principle
مبدأ تصميم ينص على قابلية استخدام نسخة الصنف الابن بسلاسة في أي موضع يتوقع نسخة من الصنف الأب.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. تنقل بين التبويبات الثلاثة في المحاكي للتحقق من ترتيب super() وحماية الحقل #pin وفحص شجرة instanceof.

  2. افتح محرر التجربة في الموضوع الخامس وأضف صنفاً فرعياً Circle extends Shape يحسب المساحة ويعرضها.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

10أسئلة 2أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي10 أسئلة تنتظرك
01

ما الكلمة المحجوزة التي تنشئ صنفاً فرعياً يرث دوال النموذج الأولي من صنف أب في JavaScript؟

02

ماذا يحدث إذا أسند باني الصنف الابن القيمة this.role = "pro" قبل استدعاء super()؟

03

إذا لم يكتب الصنف الفرعي دالة constructor، يمرر المحرك تلقائياً جميع المعاملات إلى super(...args).

04

داخل الدالة المخصصة format(msg) في الصنف الابن، كيف تستدعي نسخة الدالة الأصلية الموجودة في الصنف الأب؟

05

يستطيع الصنف الابن قراءة وتعديل الحقل الخاص #secret المصرح عنه في الصنف الأب مباشرةً عبر this.#secret.

06

كيف يتيح الصنف الأب لأصنافه الفرعية قراءة بيانات حقل خاص #private بطريقة آمنة ومنضبطة؟

07

بافتراض class Dog extends Animal {} وتنفيذ const d = new Dog()، ما ناتج (d instanceof Dog && d instanceof Animal)؟

08

يربط التصريح class Child extends Parent خلف الكواليس النموذج الأولي Child.prototype بـ Parent.prototype.

09

هل يستطيع صنف مخصص في JavaScript وراثة البواني المدمجة في اللغة مثل Error لإنشاء أخطاء مخصصة؟

10

تُعد هياكل الوراثة الضحلة من مستوى أو مستويين أسهل صيانةً وأقل هشاشة من سلاسل الوراثة العميقة المعقدة.