الوراثة والكلمة المفتاحية extends
الوراثة والكلمة المفتاحية extends
من أقوى الأفكار في البرمجة كائنية التوجه هي الوراثة — أي قدرة فئة ما على استلام حقول وتوابع فئة أخرى تلقائيًا. بدلًا من كتابة نفس الكود في خمسة أماكن، تكتبه مرّة واحدة في الفئة الأم (Superclass) وتتيح لكل فئة مشتقة (Subclass) ذات صلة إعادة استخدامه مجانًا.
علاقة "هو نوع من" (Is-A)
قبل أن تبدأ الكتابة، اطرح سؤالًا واحدًا: هل تمثّل فئتي الجديدة نسخة أكثر تحديدًا من فئة موجودة؟ إذا كان Dog (كلب) هو نوع من Animal (حيوان)، فهذه علاقة "هو نوع من"، والوراثة هي الأداة المناسبة. أما إذا كانت Car (سيارة) تحتوي على Engine (محرك)، فهذه علاقة "يمتلك" — استخدم التركيب بدلًا من الوراثة (سنتناول ذلك في درس لاحق).
Dogهو نوع منAnimal— مناسب للوراثة.SavingsAccountهو نوع منBankAccount— مناسب للوراثة.CarتمتلكEngine— استخدم التركيب لا الوراثة.
extends.
الفئة الأم والفئة المشتقة
في Java تُسمّى الفئة التي يُرِث منها غيرها الفئة الأم (Superclass)، وتُعرف أيضًا بالفئة الأساسية أو الفئة الجذر. أما الفئة التي ترِث فتُسمّى الفئة المشتقة (Subclass)، وتُعرف بالفئة الفرعية أو الفئة المُشتقّة. تُنشئ هذه العلاقة باستخدام الكلمة المفتاحية extends.
تمتد Dog من Animal، لذا يمتلك كل كائن Dog تلقائيًا name وage وeat() وsleep() — دون سطر إضافي واحد داخل فئة Dog. تعرّف فئة Dog فقط ما يجعل الكلب مختلفًا عن الحيوان العام: حقل breed والتابع bark().
ما الذي يُوَرَّث؟
ترث الفئة المشتقة كل ما تعلنه الفئة الأم بصلاحية public أو protected. تحديدًا:
- حقول الكائن (Instance Fields) — مثل
nameوageفي المثال أعلاه. - توابع الكائن (Instance Methods) — مثل
eat()وsleep(). - الأعضاء الساكنة (Static Members) — تُوَرَّث أيضًا، وإن كانت التوابع الساكنة لا تخضع للتوزيع متعدد الأشكال.
ما لا يُوَرَّث:
- الأعضاء الخاصة (Private) — الحقول والتوابع المُعلَنة بـ
privateموجودة في كائن الفئة الأم لكن لا يمكن الوصول إليها مباشرةً من الفئة المشتقة. - المُنشئات (Constructors) — لا تُوَرَّث أبدًا؛ يجب أن تعرّف الفئة المشتقة مُنشئها الخاص (أو يضيف المُترجم مُنشئًا افتراضيًا). يمكنك استدعاء مُنشئ الفئة الأم باستخدام
super()، وهو ما سنتناوله في الدرس التالي.
Dog، يُهيَّأ الجزء المتعلق بـ Animal بالكامل. لكنك لا تستطيع قراءة أو كتابة الحقول private في الفئة الأم مباشرةً؛ استخدم protected أو توابع getter العامة بدلًا من ذلك.
مثال قابل للتشغيل
لنجمع كل ما سبق ونشغّله:
المُخرجات:
لم تعرّف Dog eat() أو sleep()، ومع ذلك استدعيناهما على كائن من نوع Dog دون أي مشكلة. هذه هي الوراثة في العمل.
التمديد المتعدد المستويات (Multi-Level Inheritance)
تتيح Java أن تكون الفئة المشتقة بدورها فئةً أمًا لفئة أخرى. يمكنك إنشاء سلسلة مثل Animal ← Dog ← GuideDog. كل مستوى يرث كل شيء من المستويات الأعلى منه.
يمتلك كائن GuideDog الآن name وage وbreed وeat() وsleep() وbark() وguide() — مُتراكِمة عبر ثلاثة مستويات.
لماذا تهمّ الوراثة؟
تمنحك الوراثة ثلاث فوائد ملموسة:
- إعادة استخدام الكود — اكتب السلوك المشترك مرّة واحدة في الفئة الأم بدلًا من تكراره عبر فئات متعددة.
- قابلية التوسع — أضف نوعًا جديدًا من
Animalبإنشاء فئة مشتقة جديدة؛ الكود المشترك لا يتغير. - تعدد الأشكال (Polymorphism) — يمكن لمتغير من نوع
Animalأن يحملDogأوCatأو أي فئة مشتقة أخرى. هذا موضوع الدرس الخامس ويفتح أمامك بعضًا من أقوى أنماط Java.
الخلاصة
استخدم الكلمة المفتاحية extends عندما تكون للفئة الجديدة علاقة "هو نوع من" حقيقية مع فئة موجودة. ترث الفئة المشتقة جميع أعضاء الفئة الأم ذات الصلاحية public أو protected، وتضيف تخصصاتها الخاصة فوقها. لا تُوَرَّث المُنشئات ولا الأعضاء private. في الدرس التالي سنتناول super وكيفية استدعاء مُنشئ الفئة الأم بشكل صحيح.