الإرث في جافا هو أحد المفاهيم الأساسية في البرمجة الشيئية. يتم استخدام الإرث في جافا عندما يكون هناك علاقة “هو” بين الكائنات. يتم تنفيذ الإرث في جافا باستخدام الكلمة الرئيسية extends
.
الإرث في جافا
الإرث في جافا هو الطريقة لإنشاء تسلسل هرمي بين الفئات من خلال الاقتراض من الفئات الأخرى.
الإرث في جافا هو متعدد الاتجاهات – لذا إذا كانت Sedan تمتد من Car و Car تمتد من Vehicle، فإن Sedan موروثة أيضًا من فئة Vehicle. يصبح الفئة Vehicle فئةً فوقية لكل من Car و Sedan.
يتم استخدام الإرث على نطاق واسع في تطبيقات جافا، على سبيل المثال تمديد فئة الاستثناء لإنشاء فئة استثناء محددة للتطبيق تحتوي على مزيد من المعلومات مثل رموز الأخطاء. على سبيل المثال NullPointerException.
مثال على الإرث في جافا
كل فئة في جافا تمتد ضمنيًا من فئة java.lang.Object
. لذا تكون فئة Object في أعلى مستوى من التسلسل الهرمي للإرث في جافا.
لنرى كيفية تنفيذ الإرث في جافا من خلال مثال بسيط.
الفئة الأب: Animal
package com.journaldev.inheritance;
public class Animal {
private boolean vegetarian;
private String eats;
private int noOfLegs;
public Animal(){}
public Animal(boolean veg, String food, int legs){
this.vegetarian = veg;
this.eats = food;
this.noOfLegs = legs;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public String getEats() {
return eats;
}
public void setEats(String eats) {
this.eats = eats;
}
public int getNoOfLegs() {
return noOfLegs;
}
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
الحيوان هو الفئة الأساسية هنا. دعونا ننشئ فئة القط التي ترث من الفئة الحيوانية.
الفئة الفرعية: القط
package com.journaldev.inheritance;
public class Cat extends Animal{
private String color;
public Cat(boolean veg, String food, int legs) {
super(veg, food, legs);
this.color="White";
}
public Cat(boolean veg, String food, int legs, String color){
super(veg, food, legs);
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
لاحظ أننا نستخدم الكلمة المفتاحية extends
لتنفيذ التوريث في جافا.
برنامج اختبار التوريث في جافا
لنكتب فئة اختبار بسيطة لإنشاء كائن قط واستخدام بعض من أساليبه.
package com.journaldev.inheritance;
public class AnimalInheritanceTest {
public static void main(String[] args) {
Cat cat = new Cat(false, "milk", 4, "black");
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat eats " + cat.getEats());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
System.out.println("Cat color is " + cat.getColor());
}
}
الناتج:
فئة القط ليست لديها طريقة getEats()
ومع ذلك، البرنامج يعمل لأنها موروثة من فئة الحيوان.
نقاط مهمة
-
إعادة استخدام الكود هي الفائدة الأكثر أهمية للتوريث لأن الفئات الفرعية ترث المتغيرات والطرق من الفئة الأساسية.
-
الأعضاء الخاصة في الفئة الأساسية ليست مباشرة قابلة للوصول للفئة الفرعية. كما هو الحال في هذا المثال، المتغير الحيواني noOfLegs ليس متاحًا لفئة القط مباشرة ولكن يمكن الوصول إليه بشكل غير مباشر عبر طرق getter و setter.
-
الأعضاء في الفئة الأب مع وصول افتراضي قابلة للوصول للفئة الفرعية فقط إذا كانوا في نفس الحزمة.
-
البناؤون للفئة الأب لا يتمورثون إلى الفئة الفرعية.
-
إذا لم تحتوي الفئة الأب على بنّافتراضي، فإن الفئة الفرعية يجب أن تعرّف بنّاً صريحاً. وإلا، سيتم ذلك خطأ في وقت الترجمة. في بناء الفئة الفرعية، يجب استدعاء بناء الفئة الأب بشكل إجباري في هذه الحالة، ويجب أن يكون البيان الأول في بناء الفئة الفرعية.
-
جافا لا تدعم الوراثة المتعددة، يمكن للفئة الفرعية أن تمد فئة واحدة فقط. فئة الحيوان تمد بشكل ضمني فئة الكائن والقط يمد فئة الحيوان لكن بسبب طبيعة الوراثة العابرة في جافا، فإن فئة القط تمد أيضًا فئة الكائن.
-
يمكننا إنشاء مثيل للفئة الفرعية ثم تعيينه لمتغير الفئة الأم، وهذا يسمى التصعيد. فيما يلي مثال بسيط على التصعيد:
القط ج = جديد القط(); // مثيل الفئة الفرعية الحيوان أ = ج; // التصعيد، هذا جيد لأن القط أيضًا حيوان
-
عندما يتم تعيين مثيل من الفئة الأعلى إلى متغير من الفئة الفرعية، فإن ذلك يسمى التحويل الهابط (Downcasting). يجب علينا تحويل هذا بشكل صريح إلى الفئة الفرعية. على سبيل المثال؛
Cat c = new Cat(); Animal a = c; Cat c1 = (Cat) a; //casting صريح، يعمل بشكل صحيح لأن "c" هو في الواقع من نوع Cat
لاحظ أن المترجم (Compiler) لن يشكو حتى لو كنا نفعل ذلك بشكل خاطئ، بسبب التحويل الصريح. فيما يلي بعض الحالات التي ستتسبب في رمي استثناء
ClassCastException
أثناء التشغيل.Dog d = new Dog(); Animal a = d; Cat c1 = (Cat) a; //ClassCastException أثناء التشغيل Animal a1 = new Animal(); Cat c2 = (Cat) a1; //ClassCastException لأن a1 هو في الواقع من نوع Animal أثناء التشغيل
-
يمكننا تجاوز الطريقة (method) من الفئة الأعلى في الفئة الفرعية. ومع ذلك، يجب علينا دائمًا وضع تعليق @Override فوق الطريقة التي تم تجاوزها. سيعرف المترجم أننا نقوم بتجاوز الطريقة وإذا تغير شيء في طريقة الفئة الأعلى، سنحصل على خطأ في وقت الترجمة بدلاً من الحصول على نتائج غير مرغوب فيها أثناء التشغيل.
-
يمكننا استدعاء طرق الفئة الأساسية والوصول إلى متغيرات الفئة الأساسية باستخدام الكلمة الرئيسية super. يأتي هذا بمساعدة عندما يكون لدينا متغير/طريقة بنفس الاسم في الفئة الفرعية ولكن نريد الوصول إلى متغير/طريقة الفئة الأساسية. يتم استخدام هذا أيضًا عندما يتم تعريف المنشئون في الفئة الأساسية والفئة الفرعية ويتعين علينا استدعاء منشئ الفئة الأساسية بوضوح.
-
يمكننا استخدام التعليمة
instanceof
للتحقق من التوريث بين الكائنات، دعونا نرى هذا من خلال المثال أدناه.
```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;
boolean flag = c instanceof Cat; //normal case, returns true
flag = c instanceof Animal; // returns true since c is-an Animal too
flag = an instanceof Cat; //returns true because a is of type Cat at runtime
flag = an instanceof Dog; //returns false for obvious reasons.
```
- لا يمكننا توسيع الفئات النهائية في جافا.
- إذا كنت لن تستخدم الفئة الأساسية في الشيفرة، أي أن فئتك الأساسية هي مجرد قاعدة للحفاظ على الشيفرة القابلة لإعادة الاستخدام، فيمكنك الاحتفاظ بها كـ فئة مجردة لتجنب إنشاء غير ضروري بواسطة فئات العملاء. وسيمنع ذلك أيضًا إنشاء الحالة لفئة الأساس.
درس الفيديو حول التوريث في جافا
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
يمكنك التحقق من المزيد من أمثلة التوريث من مستودعنا على GitHub.
المرجع: توثيق أوراكل
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example