الوراثة مفهوم أساسي في البرمجة كائنية التوجه (Object-Oriented Programming). وهي تمثّل علاقة "هو نوع من". ومعناها في البرمجة هو نفسه معناها في اللغة الإنجليزية: أن ترث الخصائص من الأب (وفي البرمجة تكون الخصائص عادةً دوال ومتغيرات).
لننظر إلى صنف باسم Animal كما في المثال التالي،
//Creating an Animal class with bark() as a member function.
public class Animal {
public void bark() {
System.out.println("This is an animal");
}
}
الصنف Animal هو صنف أب، لأن الخصائص التي يمتلكها هذا الصنف يمكن أن تمتد إلى كل الحيوانات عمومًا.
لننظر إلى حيوان باسم Lion، له صنف كالتالي:
//Lion class is a child class of Animal.
public class Lion extends Animal {
@Override
public void bark() {
System.out.println("Lion here!!");
}
}
يُستخدم التعليق التوضيحي Override للإشارة إلى أن طريقة في صنف فرعي تتجاوز طريقة في صنفها الأعلى.
وهو ليس ضروريًا تمامًا، لكن استخدامه من الممارسات الجيدة.
الآن، عندما نكتب ما يلي،
Animal animal = new Lion(); //creating instance of Animal, of type Lion
animal.bark();
ملاحظة: هنا نهيّئ الصنف Animal بواسطة Lion.
وستكون المخرجات كالتالي
Lion here!!
وفقًا للبرمجة كائنية التوجه، هناك أنواع كثيرة للوراثة، لكن Java تدعم بعضها فقط (الوراثة متعددة المستويات والوراثة الهرمية). لمعرفة المزيد عنها، اقرأ هذا.
في هذا التمرين، ستلعب لعبة تقمّص أدوار يمكن فيها لأنواع مختلفة من المقاتلين أن تتقاتل فيما بينها.
لكل نوع من المقاتلين قواعد مختلفة في اللعبة.
سنركّز على نوعين محددين: Wizard وWarrior.
بالنسبة إلى Warrior، هذه هي القواعد:
Warrior معرّضًا للضرر أبدًا.Warrior 6 نقاط ضرر إذا لم يكن المقاتل الذي يهاجمه معرّضًا للضرر.Warrior 10 نقاط ضرر إذا كان المقاتل الذي يهاجمه معرّضًا للضرر.بالنسبة إلى Wizard، هذه هي القواعد:
Wizard تحضير تعويذة مسبقًا.Wizard معرّضًا للضرر ما لم يحضّر تعويذة مسبقًا.Wizard 12 نقطة ضرر إذا حضّر تعويذة مسبقًا.Wizard 3 نقاط ضرر إذا لم يحضّر تعويذة مسبقًا.Warrior
أنشئ صنفًا جديدًا باسم Warrior.
ينبغي أن يرث هذا الصنف من صنف Fighter الموجود.
Warrior
حدّث صنف Warrior بحيث تصف طريقة toString() نوع المقاتل الذي يمثله.
ينبغي أن تُرجع الطريقة السلسلة النصية "Fighter is a Warrior".
Warrior warrior = new Warrior();
warrior.toString();
// => "Fighter is a Warrior"
Warrior غير معرّض للضررحدّث صنف Warrior بحيث تُرجع طريقة isVulnerable() القيمة false دائمًا.
Warrior warrior = new Warrior();
warrior.isVulnerable();
// => false
Warrior
حدّث صنف Warrior بحيث تحسب طريقة getDamagePoints(Fighter) الضرر الذي يُلحقه Warrior وفقًا للقواعد أعلاه.
Warrior warrior = new Warrior();
Wizard wizard = new Wizard();
warrior.getDamagePoints(wizard);
// => 10
Wizard
أنشئ صنفًا جديدًا آخر باسم Wizard.
ينبغي أن يرث هذا الصنف أيضًا من صنف Fighter الموجود.
Wizard
حدّث صنف Wizard بحيث تصف طريقة toString() نوع المقاتل الذي يمثله.
ينبغي أن تُرجع الطريقة السلسلة النصية "Fighter is a Wizard".
Wizard wizard = new Wizard();
wizard.toString();
// => "Fighter is a Wizard"
Wizard بتحضير تعويذة وجعله معرّضًا للضرر عند عدم تحضير تعويذةحدّث صنف Wizard لإضافة طريقة باسم prepareSpell().
ينبغي أن يتذكر الصنف وقت استدعاء هذه الطريقة، وأن يحرص على ألا تُرجع طريقة isVulnerable() القيمة false إلا عند تحضير تعويذة.
Wizard wizard = new Wizard();
wizard.prepareSpell();
wizard.isVulnerable();
// => false
Wizard
حدّث صنف Wizard بحيث تحسب طريقة getDamagePoints(Fighter) الضرر الذي يُلحقه Wizard وفقًا للقواعد أعلاه.
Wizard wizard = new Wizard();
Warrior warrior = new Warrior();
wizard.prepareSpell();
wizard.getDamagePoints(warrior);
// => 12
سجّل في Exercism لتتعلّم وتتقن Java عبر 26 مفهومًا158 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.