דוגמה להורשה ב-Java

עיבוד ירושה ב-Java הוא אחד מהמושגים המרכזיים של תכנות עצמים. ירושה ב-Java משמשת כאשר יש לנו יחס is-a בין אובייקטים. ירושה ב-Java מיושמת באמצעות המילה המפתחת extends.

ירושה ב-Java

ירושה ב-Java היא השיטה ליצירת היררכיה בין מחלקות על ידי ירושה ממחלקות אחרות.

ירושה ב-Java היא טרנזיטיבית – אם Sedan מרחיבה את Car ו-Car מרחיבה את Vehicle, אז Sedan גם מורשה ממחלקת Vehicle. Vehicle הופכת למחלקת אב של Car וגם של Sedan.

ירושה משמשת באופן נרחב ביישומים ב-Java, לדוג, הרחבת מחלקת Exception כדי ליצור מחלקת Exception המותאמת ליישום שמכילה מידע נוסף כמו קודי שגיאה. לדוג, NullPointerException.

דוגמה לירושה ב-Java

כל מחלקה ב-Java מרחיבה באופן משמעי את המחלקה java.lang.Object. לכן מחלקת Object נמצאת בראש ההיררכיה של הירושה ב-Java.

בואו נראה איך ליישם ירושה ב-Java עם דוגמה פשוטה.

מחלקת אב: 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(), אך עדיין, התוכנית עובדת מכיוון שהיא יורשת ממחלקת החיה.

נקודות חשובות

  1. שימוש בקוד הוא היתרון החשוב ביותר של ירושה מאחר ומחלקות מורשות מתקבלות על המשתנים והשיטות של מחלקה אב.

  2. חברים פרטיים של מחלקה אב אינם נגישים ישירות למחלקה מורשה. כפי שניתן לראות בדוגמה זו, המשתנה של החיה בשם noOfLegs אינו נגיש ישירות למחלקת החתול, אך ניתן לגשת אליו באופן עקיף דרך שיטות הקבלה והקביעה.

  3. חברי המחלקה העל עם גישת ברירת המחדל נגישים למחלקה המורישה רק אם הם נמצאים באותו חבילה.

  4. בניית המחלקה העל אינם מותרים על ידי המחלקה המורישה.

  5. אם למחלקה העל אין בנאי ברירת מחדל, אזי יש להגדיר באופן חד משמעי בנאי במחלקה המורישה. אחרת יתריע על שגיאה בזמן קומפילציה. בבנאי של המחלקה המורישה, יש לקרוא לבנאי של המחלקה העל וזה יהיה ההצהרה הראשונה בבנאי של המחלקה המורישה.

  6. Java אינה תומכת בהתורשת מרובית, תת-מחלקה יכולה להרחיב רק מחלקה אחת. מחלקת Animal מרחיבה את מחלקת Object ממש כמו שמחלקת Cat מרחיבה את מחלקת Animal אך בשל טבע ההתורשת של Java, מחלקת Cat גם מרחיבה את מחלקת Object.

  7. ניתן ליצור מופע של תת-מחלקה ולאחר מכן להקצות אותו למשתנה של מחלקה אב, זה נקרא upcasting. להלן דוגמה פשוטה ל- upcasting:

    Cat c = new Cat(); // מופע של תת-מחלקה
    Animal a = c; // upcasting, זה בסדר מאחר וגם תת-מחלקה גם כן תת-מחלקה
    
  8. כאשר מופע של המחלקה האב שיויך למשתנה של מחלקה המורשת, אז זה נקרא downcasting. עלינו להמיר זאת באופן ברור לתת מחלקה. לדוגמה;

    Cat c = new Cat();
    Animal a = c;
    Cat c1 = (Cat) a; // יצירת סוג ספציפי, עובד בסדר כי "c" בעצם מסוג Cat
    

    שימו לב שהמהדר לא יתלונן אפילו אם אנו עושים זאת בצורה שגויה, בגלל ההמרה הברורה. להלן כמה מהמקרים בהם הוא יזרוק ClassCastException בזמן ריצה.

    Dog d = new Dog();
    Animal a = d;
    Cat c1 = (Cat) a; // ClassCastException בזמן ריצה
    
    Animal a1 = new Animal();
    Cat c2 = (Cat) a1; // ClassCastException מכיוון ש-a1 בעצם מסוג Animal בזמן ריצה
    
  9. אנו יכולים לדרוס את השיטה של המחלקה האב במחלקה המורשת. אך תמיד עלינו לסמן את השיטה שדורסה עם @Override annotation. המהדר ידע שאנו דורסים שיטה ואם משהו משתנה בשיטת המחלקה האב, נקבל שגיאת זמן קומפילציה במקום לקבל תוצאות שאינם רצויות בזמן הריצה.

  10. אנו יכולים לקרוא לשיטות של המחלקה האב ולגשת אל משתני המחלקה האב באמצעות המילה השמורה super. זה משתלם כאשר יש לנו משתנה/שיטה בשם דומה בתת-המחלקה אך אנו רוצים לגשת למשתנה/שיטה של המחלקה האב. זה גם נחוץ כאשר במחלקה האב ובתת-המחלקה יש בנאי ואנו רוצים לקרוא באופן ברור לבנאי של המחלקה האב.

  11. ניתן להשתמש בהוראת 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.
```
  1. אין באפשרותנו להרחיב מחלקות סופיות ב-Java.
  2. אם אתה לא מתכוון להשתמש ב־Superclass בקוד, כלומר ה־Superclass שלך הוא רק בסיס לשמירת קוד שניתן לשימוש מחדש, אז תוכל להשאיר אותם כ־כיתה מופשטת כדי למנוע הפעלה מיותרת על ידי מחלקות הלקוח. זה גם יגביל את יצירת המופע של המחלקה הבסיסית.

הדרכה בווידאו על ירושה ב־Java

I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.


אתה יכול לבדוק דוגמאות נוספות של ירושה מה־מאגר הקוד שלנו ב־GitHub.

הפניה: תיעוד של Oracle

Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example