أهلاً! أنت تستخدم بالفعل أساليب Java وتعرف الكثير عنها. من المحتمل أنك واجهت الموقف حيث يكون لدى فئة واحدة العديد من الأساليب التي تحمل نفس الاسم ولكن بمعلمات مختلفة. ستتذكر أننا في تلك الحالات استخدمنا طريقة التحميل الزائد. اليوم نحن نفكر في وضع آخر. تخيل أن لدينا طريقة مشتركة واحدة، ولكن يجب أن تفعل أشياء مختلفة في فئات مختلفة. كيف ننفذ هذا السلوك؟ لفهم ذلك، دعونا نفكر في فئة الأصل Animal ، والتي تمثل الحيوانات، وسنقوم بإنشاء طريقة التحدث فيها:
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
على الرغم من أننا قد بدأنا للتو في كتابة البرنامج، فمن المحتمل أنك ترى مشكلة محتملة: هناك الكثير من الحيوانات في العالم، وكلها "تتكلم" بشكل مختلف: مواء القطط، وصوت البط، وهسهسة الثعابين. هدفنا بسيط: تجنب إنشاء الكثير من أساليب التحدث. بدلاً من إنشاء طريقة catSpeak() للمواء، وطريقة SnakeSpeak() للهسهسة، وما إلى ذلك، نريد استدعاء طريقة Speak() وجعل الأفعى هسهسة، ومواء القطة، ونباح الكلب. يمكننا تحقيق ذلك بسهولة باستخدام طريقة التجاوز. تقدم ويكيبيديا التفسير التالي لمصطلح "التجاوز": تجاوز الطريقة، في البرمجة كائنية التوجه، هي ميزة لغوية تسمح لفئة فرعية أو فئة فرعية بتوفير تنفيذ محدد لطريقة يتم توفيرها بالفعل بواسطة إحدى فئاتها الفائقة أو الطبقات الأم هذا صحيح في الأساس. يتيح لك تجاوز الطريقة استخدام بعض أساليب الفصل الأصلي وكتابة التنفيذ الخاص بك في كل فصل فرعي. التنفيذ الجديد "يستبدل" تطبيق الأصل في الفصل الفرعي. دعونا نرى كيف يبدو هذا في مثال. أنشئ 4 فئات ترث فئة الحيوانات لدينا :
public class Bear extends Animal {
@Override
public void speak() {
System.out.println("Growl!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void speak() {
System.out.println("Hiss!");
}
}
"إليك حيلة حياتية صغيرة للمستقبل: لتجاوز أساليب الفصل الأصلي، انتقل إلى رمز الفصل الفرعي في IntelliJ IDE، وانقر فوق Ctrl+O، واختر "تجاوز الأساليب..." في القائمة. التعود على استخدام مفاتيح التشغيل السريع منذ البداية - سيساعدك ذلك على كتابة البرامج بشكل أسرع! لتحديد السلوك الذي نحتاجه، قمنا ببعض الأشياء:
- في كل فئة فرعية، قمنا بإنشاء طريقة بنفس اسم طريقة الفئة الأصلية.
- أخبرنا المترجم أن تسمية الطريقة بنفس الطريقة كما في الفئة الأصل لم تكن مصادفة: نريد تجاوز سلوكها. لتوصيل هذا إلى المترجم، قمنا بتعيين التعليق التوضيحيOverride أعلى الطريقة.
عند وضعه فوق إحدى الطرق، يُعلم التعليق التوضيحيOverride المترجم (وكذلك المبرمجين الذين يقرؤون التعليمات البرمجية الخاصة بك): "كل شيء على ما يرام". هذا ليس خطأ. أنا لا أنسى. أدرك أن مثل هذه الطريقة موجودة بالفعل وأريد تجاوزها. - لقد كتبنا التنفيذ الذي نحتاجه لكل فئة فرعية. عندما يتم استدعاء طريقة الكلام () ، يجب أن يهسه الثعبان، ويجب أن يهدر الدب، وما إلى ذلك.
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.speak();
animal2.speak();
animal3.speak();
animal4.speak();
}
}
إخراج وحدة التحكم:
Woof!
Meow!
Growl!
Hiss!
ممتاز! كل شيء يعمل على مايرام! لقد أنشأنا 4 متغيرات مرجعية تخزن كائنات الفئة الرئيسية للحيوان ، وقمنا بتعيين مثيلات لأربعة فئات فرعية مختلفة لها. ونتيجة لذلك، كل كائن يسلك سلوكه الخاص. بالنسبة لكل فئة فرعية، حلت طريقة التحدث () التي تم تجاوزها محل طريقة التحدث () "الأصلية" في فئة الحيوان (والتي تعرض ببساطة "مرحبًا!"). التجاوز له عدة قيود:
-
يجب أن تحتوي الطريقة التي تم تجاوزها على نفس معلمات الطريقة الأصلية.
إذا كانت طريقة التحدث الخاصة بالفئة الأصلية تحتوي على معلمة سلسلة ، فيجب أن تحتوي الطريقة التي تم تجاوزها في الفئة الفرعية أيضًا على معلمة سلسلة . وإلا فإن المترجم سيولد خطأ:
public class Animal { public void speak(String s) { System.out.println("Hello! " + s); } } public class Cat extends Animal { @Override // Error! public void speak() { System.out.println("Meow!"); } }
-
يجب أن يكون للطريقة التي تم تجاوزها نفس نوع الإرجاع مثل الطريقة الأصلية.
وإلا فسنحصل على خطأ في المترجم:
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override public String speak() { // Error! System.out.println("Meow!"); return "Meow!"; } }
-
يجب أيضًا أن يكون معدل الوصول في الطريقة التي تم تجاوزها هو نفس الطريقة "الأصلية":
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override private void speak() { // Error! System.out.println("Meow!"); } }
GO TO FULL VERSION