جافاسكربتالوراثة
- مفهوم الوراثة
- الكلمة المفتاحية extends
- أمثلة على أشكال الوراثة
- الكلمة المفتاحية super
مفهوم الوراثة
إبتداءاًَ من الإصدار ES6 أصبحت جافاسكربت تدعم الوراثة ( Inheritance ) و التي تعني أن الكلاس يمكنه أن يرث من كلاس آخر و بالتالي يحصل على جميع الدوال و المتغيرات الموجودة فيه.
الوراثة يمكن الإستفادة منها للحد من تكرار الكود، فمثلاً إذا كنت تريد إنشاء كلاس جديد و كان لديك كلاس جاهز يحتوي على متغيرات و دوال تحتاج أن تكتبها فيه، فيمكنك جعل الكلاس يرثها كما هي بدلاً من إعادة تعريفها فيه، و بعدها يمكنك إستخدام جميع المتغيرات و الدوال التي ورثها الكلاس الجديد من الكلاس الجاهز.
مفهوم الكلاس الأب و الكلاس الإبن
- الكلاس الذي يرث من كلاس آخر يعتبر بمثابة إبن له لذلك يقال له Subclass أو Derived class أو Extended class أو Child class.
- الكلاس الذي يوّرث محتوياته لكلاس آخر يعتبر بمثابة أب له لذلك فيقال له Superclass أو Base class أو Parent class.
الكلاس الإبن يرث كل المتغيرات، الخصائص و الدوال العامة الموجودة فيه ما عدا الكونستركتور و الدوال الثابتة الموجودة فيه.
الكلمة المفتاحية extends
لجعل الكلاس يرث من كلاس آخر نستخدم الكلمة المفتاحية extends على النحو التالي.
// Child class body
}
- childClass — يقصد بها إسم الكلاس الإبن.
- parentClass — يقصد بها إسم الكلاس الأب.
- Child class body — يقصد بها الأشياء الخاصة بالكلاس الإبن إضافةً إلى الأشياء التي ورثها من الكلاس الأب.
أمثلة على أشكال الوراثة
في جافاسكربت يوجد 3 أشكال للوراثة كما هو موضح في الجدول التالي.
إذاَ أشكال الوراثة في جافاسكربت هي كالتالي:
- وراثة فردية — تعني كلاس يرث من كلاس واحد فقط.
- وراثة متتالية — تعني كلاس يرث من كلاس و الذي بدوره يرث من كلاس آخر.
- وراثة هرمية — تعني أن الكلاس موروث من قبل أكثر من كلاس.
في جافاسكربت، الكلاس يمكنه أن يرث بشكل مباشر من كلاس واحد فقط.
مثال عن الوراثة الفردية
في المثال التالي قمنا بتعريف كلاس إسمه A يحتوي على متغير إسمه x و دالة إسمها printMessage().
بعدها قمنا بإنشاء كلاس إسمه B يحتوي على متغير إسمه y و يرث من الكلاس A.
مثال
نتيجة التشغيل:
x = 10
Hello from class A
مثال عن الوراثة المتتالية
في المثال التالي قمنا بتعريف كلاس إسمه A يحتوي على دالة إسمها printA().
بعدها قمنا بإنشاء كلاس إسمه B يحتوي على دالة إسمها printB() و يرث من الكلاس A.
بعدها قمنا بإنشاء كلاس إسمه C يحتوي على دالة إسمها printC() و يرث من الكلاس B.
مثال
نتيجة التشغيل:
Hello from class B
Hello from class C
مثال عن الوراثة الهرمية
في المثال التالي قمنا بتعريف كلاس إسمه A يحتوي على دالة إسمها printA().
بعدها قمنا بإنشاء كلاس إسمه B يحتوي على دالة إسمها printB() و يرث من الكلاس A.
بعدها قمنا بإنشاء كلاس إسمه C يحتوي على دالة إسمها printC() و يرث من الكلاس A أيضاً.
مثال
نتيجة التشغيل:
Hello from class B
Hello from class A
Hello from class C
الكلمة المفتاحية super
بشكل عام، نستخدم الكلمة super للتفرقة بين الأشياء الموجودة في الكلاس الإبن و الكلاس الأب إذا كانت تحمل نفس الإسم.
إفتراضياً، مفسر الكود يعطي الأولوية لاستخدام الشيء الموجود في الكلاس الإبن و لكن لو أردنا إعلام مفسر الكود أننا نريد استدعاء الشيء الموجود في الكلاس الأب فإننا نكتب قبله الكلمة super.
طريقة استخدام الكلمة super
فيما يلي طريقة استخدامها لاستدعاء خاصية موجودة في الكلاس الأب بدلاً من استخدام خاصيّة الكلاس الإبن.
فيما يلي طريقة استخدامها لاستدعاء دالة موجودة في الكلاس الأب بدلاً من استخدام دالة الكلاس الإبن.
فيما يلي طريقة استخدامها لاستدعاء متغير أو خاصية موجودة في الكلاس الأب.
إذا كان كونستركتور أو دالة الكلاس الأب يحتوي على باراميترات فلا تنسى أن تمرر قيم لها و إلا فإن ذلك سيسبب مشكلة.
إستدعاء كونستركتور الكلاس الأب
بشكل عام، في حال كان الكلاس الأب يحتوي على كونستركتور فإنه لا بد للكلاس الإبن من أن يقوم باستدعائه حتى يعمل الكود بشكل صحيح.
- إذا كان كونستركتور الكلاس الأب ليس فيه باراميترات و الكلاس الإبن لا يملك كونستركتور فإنه سيتم استدعاء كونستركتور الكلاس الأب بشكل تلقائي عند إنشاء كائن من الكلاس الإبن.
- إذا كان كونستركتور الكلاس الأب يحتوي على باراميترات فإن الكلاس الإبن سيكون مجبر على أن يمتلك باراميتر خاص به و عليه أن يستدعي كونستركتور الكلاس الأب بداخله.
- إذا كان الكلاس الإبن يحتوي على كونستركتور فيجب عليه أن يستدعي بداخله كونستركتور الكلاس الأب حتى لو كان سيستدعي الكونستركتور الإفتراضي الذي ينشئه له مفسر الكود.
يفضّل دائماً أن يتم تعريف الكونستركتور في كل من الكلاس الإبن و الكلاس الأب و لو كان فارغاً حتى تكون العلاقة واضحة بالنسبة للمبرمج إذا ما أراد تعديل الكود في وقت لاحق أو مشاركته مع الغير.
في المثال التالي قمنا بتعريف كونستركتور فارغ الكلاس الأب حتى تلاحظ كيف أنه سيتم استدعاؤه بشكل تلقائي عند إنشاء كائن من الكلاس الإبن.
المثال الأول
نتيجة التشغيل:
في المثال التالي قمنا بتعريف كونستركتور في الكلاس الأب.
هنا الكلاس الإبن أصبح مجبر على أن يمتلك كونستركتور خاص به و يجب عليه أن يستدعي بداخله كونستركتور الكلاس الأب.
في النهاية، لاحظ كيف أنه عندما قمنا بإنشاء كائن من الكلاس الإبن كيف أنه تم تنفيذ كونستركتور الكلاس الأب و كونستركتور الكلاس الإبن.
المثال الثاني
نتيجة التشغيل:
Constructor of class B is called
في المثال السابق، لو لم نستدعي كلاس الكلاس الأب في كونستركتور الكلاس الإبن لظهرت مشكلة في الكونسول و لما تم تنفيذ كونستركتور الكلاس الأب كما يفترض.
في المثال التالي قمنا بتعريف كونستركتور و خاصية و دالة في الكلاس الأب.
في الكلاس الإبن قمنا بإعادة تعريف الكونستركتور و الدالة التي ورثها الكلاس الإبن و أضفنا على الكلاس خصائص جديدة.
المثال الثالث
نتيجة التشغيل:
y = 20
z = 30