مفهوم الـ Overriding
في الدرس السابق, شاهدت كيف أن الـ Subclass يرث المتغيرات و الدوال الموجودة في الـ Superclass. و تعلمت أيضاً أنه يمكن للـ Subclass إعادة تعريف أي دالة ورثها من الـ Superclass شرط أن لا تكون معرفة كـfinal
, و كتابة الكلمة @Override
قبل تعريفها من جديد حتى تتفادى حدوث مشاكل عند ترجمة الكود.Override: تعني تعريف الدالة التي ورثها الـ Subclass من الـ Superclass من جديد, هذه الدالة الجديدة تكون مشابهة للدالة الموروثة من حيث الشكل فقط, أي لها نفس الإسم و النوع و عدد الباراميترات, لكن محتواها مختلف.
الهدف الحقيقي من الـ Overriding هو إتاحة الفرصة للـ Subclass ليعرف الدوال حسب حاجته.
في دروس متقدمة سنرث من كلاسات جاهزة في جافا, و نفعل Override للدوال الموجودة فيها لكي تناسب التطبيقات التي سنقوم ببنائها.
مثال
الآن لنفترض أننا قمنا بتعريف كلاس إسمهCountry
, يحتوي على دالة إسمها language()
.بعدها قمنا بتعريف ثلاث كلاسات, و كلها ترث من
Country
, إذاً كلها ستحتوي على الدالة language()
.هنا الفكرة أن أي كلاس يرث من
Country
قد يضطر إلى تعريف الدالة language()
من جديد حتى تناسبه.بعد إنشاء هذه الكلاسات, سنقوم بإنشاء الكلاس
Test
لتجربتهم.package inheritance; public class Country {// هنا, هذا الكلاس يعتبر الكلاس الأساسي لأي دولة في العالم, إذاً يجب أن يرثه أي كلاس يمثل دولة public void language() { System.out.println("English"); // هنا قمنا بوضع اللغة الإنجليزية كلغة إفتراضية لجميع البلدان } }
package inheritance; public class Australia extends Country{// من جديد لأن اللغة الإنجليزية هي لغة أستراليا language() هنا لا داعي لتعريف الدالة }
package inheritance; public class Lebanon extends Country{// من جديد لأن اللغة الإنجليزية ليست لغة لبنان language() هنا يجب تعريف الدالة @Override public void language(){ System.out.println("Arabic"); } }
package inheritance; public class Spain extends Country{ // من جديد لأن اللغة الإنجليزية ليست لغة إسبانيا language() هنا يجب تعريف الدالة @Override public void language(){ System.out.println("Spanish"); } }
package inheritance; public class Test{ public static void main(String[] args){ // هنا قمنا بإنشاء كائنات من البلدان الثلاثة Australia au = new Australia(); Lebanon lb = new Lebanon(); Spain sp = new Spain(); //لعرض لغة كل بلد language() هنا قمنا باستدعاء الدالة au.language(); lb.language(); sp.language(); } }
English Arabic Spanish
أنت الآن فهمت لما قد تحتاج أن تفعل Override. سنقوم الآن بشرح طريقة عمل مترجم جافا عندما فعلت Override للدالة
language()
.إذا عدت للكلاس Lebanon, ستجد أننا فعلنا Override للدالة language(). إذاً هنا أصبح الكلاس Lebanon يملك دالتين إٍسمهما language(), الأولى هي التي ورثها من الـ Superclass, و الثانية هي التي قمنا بتعريفها عندما فعلنا Override.
بما أن الكلاس Lebanon يملك دالتين لهما نفس الإسم, النوع و عدد البارامتيرات, كيف عرف أي دالة يختار؟
عندما قمنا بتعريف الدالة language() من جديد في الـ Subclass, قام المترجم بإخفاء الدالة الأصلية ( أي دالة الـ Superclass ) و أظهر الدالة الجديدة فقط. بالإضافة إلى أن الكلمة @Override ضمنت لنا حصول هذا, لأنها تخبر المترجم أنه يوجد عدة دوال إسمهم language() لكننا نريد هذه الدالة بالتحديد عند استدعائها من هذا الكلاس.
إنتبه: في داخل الكلاس Lebanon, إذا أردنا إستخدام الدالة language() الموجودة في الـ Superclass و التي قام المترجم بإخفائها عندما قمنا بتعريفها من جديد, يمكننا ذلك بواسطة الكلمة super التي شرحناها في الدرس السابق.
شروط الـ Overriding للدوال
يجب أن يكون الـ Modifier المستخدم للدالة الجديدة هو نفسه المستخدم للدالة القديمة, و يجب أن يكون نوعه public أو protected.
عدد و نوع باراميترات الدالة الجديدة يجب أن يطابق عدد و نوع باراميترات الدالة القديمة.
نوع الإرجاع للدالة الجديدة يجب أن يكون نفس نوع الإرجاع للدالة القديمة.
الدالة المعرفة كـ private لا يمكن أن نفعل لها Override, لأن كلمة private تمنع إمكانية الوصول المباشر للدالة من الـ Subclass.
الدالة المعرفة كـ final لا يمكن أن نفعل لها Override, لأن كلمة final تمنع تغير محتوى الدالة بعد تعريفها.
الدالة المعرفة كـ static لا يمكن أن نفعل لها Override و لكن يمكن تعريفها من جديد في أي مكان, لأن كلمة static تجعل الدالة مشتركة بين جميع الكلاسات.
لا يمكن أن نفعل Override للكونستركتور.
تطبيق أخر علي مفهوم overriding
في هذا المثال لدينا كلاس إسمه human وهو كلاس مورث parent class وكلاس أخر إسمه Boy وهو وارث child class ويستطيع تفعيل خاصية overriding لكل دالة موجودة في الكلاس الاب Human ويستخدمه كما يشاءclass Human{ //Overridden method public void eat() { System.out.println("Human is eating"); } } class Boy extends Human{ //Overriding method @Override //يمكن الاستغناء عن هذه الكلمة في بعض الحالات لكل يفضل كتابته لتعرف بها أن هذه الدالة تمت كتابته سابقا public void eat(){ System.out.println("Boy is eating"); } public static void main( String args[]) { Boy obj = new Boy();//هنا تم تعريف كائن من الكلاس Boy ويستطيع هذا الكائن الوصول لكل الدوال المعرفة في الكلاس غير المحمية obj.eat(); //هنا تم إستدعاء الدالة eat() بواسطة الكائن obj Human obj2 = new Human();//هنا تم إنشاء كائن من الكلاس Human ويستطيع الوصول لكل دالة غير محمية private obj2.eat();//هنا تم إستدعاء الدالة eat() التي موجودة في الكلاس Human وليس الكلاس Boy } }
Boy is eating
Human is eating
Human is eating
مثال أخر
class ABC{ //Overridden method public void disp() { System.out.println("disp() method of parent class"); } } class Demo extends ABC{ //Overriding method public void disp(){ System.out.println("disp() method of Child class"); } public void newMethod(){ System.out.println("new method of child class"); } public static void main( String args[]) { ABC obj = new ABC(); obj.disp(); ABC obj2 = new Demo(); obj2.disp(); } }
disp() method of parent class
disp() method of Child class
disp() method of Child class
ليست هناك تعليقات:
إرسال تعليق
ملحوظة: يمكن لأعضاء المدونة فقط إرسال تعليق.