JavaRush /בלוג Java /Random-HE /יסודות מופע וירושה

יסודות מופע וירושה

פורסם בקבוצה
שלום! בהרצאות קודמות כבר נתקלנו בקצרה במושג הירושה מספר פעמים. היום ניגע גם בנושא הזה, אבל גם לא יותר מדי. תהיה הרצאה מפורטת על כך בהמשך, אבל היום רק נסתכל על דוגמאות מעשיות ונכיר מפעיל מעניין אחד בג'אווה.

תורשת ג'אווה

אז מהי בעצם ירושה? יסודות מופע וירושה - 1ירושה הוא מנגנון בתכנות, כולל Java, המאפשר לתאר מחלקה חדשה על סמך מחלקה קיימת. לאחר מכן המחלקה הצאצאית מקבלת גישה לשדות ולשיטות של מחלקת האב. למה זה עשוי להיות נחוץ? ובכן, למשל, תארו לעצמכם שאתם צריכים ליצור מספר מחלקות של מכוניות בתוכנית: משאית, מירוץ, סדאן, טנדר וכו'. גם בלי להתחיל לכתוב קוד, אתה יודע בוודאות שלמחלקות הללו יש הרבה מן המשותף: לכל המכוניות יש שם דגם, שנת ייצור, גודל מנוע, מהירות מרבית וכו'. (שלא לדבר על העובדה שלכולם יש גלגלים וחלקים אחרים). במצב כזה, אתה יכול:
  • צור שדות אלה בכל מחלקה והוסף אותם למחלקות מכוניות חדשות כאשר הם נוצרים
  • העבר את השדות המשותפים לכל המכונות למחלקת האב Car, וכל המחלקות של סוגים ספציפיים של מכונות יורשים מהשימוש Carבמילה extends .
האפשרות השנייה, כמובן, הרבה יותר נוחה:
public class Car {

   private String model;
   private int maxSpeed;
   private int yearOfManufacture;

   public Car(String model, int maxSpeed, int yearOfManufacture) {
       this.model = model;
       this.maxSpeed = maxSpeed;
       this.yearOfManufacture = yearOfManufacture;
   }
}

public class Truck extends Car {

   public Truck(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}

public class Sedan extends Car {
   public Sedan(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}
לכל הפחות, נמנענו משכפול מיותר של קוד, וזה משהו שאנחנו צריכים תמיד לשאוף אליו בעת כתיבת תוכניות. בנוסף, יש לנו מבנה מחלקה פשוט ומובן: שדות משותפים לכל המכונות ממוקמים במחלקה אחת. אם, למשל, למשאיות יש שדות ספציפיים שאין למכוניות אחרות, ניתן להצהיר עליהם ב- Truck. כך גם לגבי שיטות. לכל המכוניות יש התנהגות משותפת שניתן לתאר: התנעת המכונית, דלק/בלימה וכו'. ניתן למקם את השיטות הכלליות הללו במחלקה כללית Car, וניתן לתאר את ההתנהגות הספציפית של כל סוג ספציפי במחלקות צאצאות.
public class Car {

   public void gas() {
       //...gas
   }

   public void brake() {
       //...brake
   }
}


public class F1Car extends Car {

   public void pitStop() {

       //...only racing cars make pit stops
   }

   public static void main(String[] args) {

       F1Car formula1Car = new F1Car();
       formula1Car.gas();
       formula1Car.pitStop();
       formula1Car.brake();
   }
}
העברנו את השיטות הנפוצות של כל המכוניות לכיתה Car. אבל במעמד היורש F1Car, שמתאר מכוניות מירוץ פורמולה 1 - עצירות פיט (עצירות לתחזוקה דחופה של המכונית), שנעשות רק במירוץ ונבדלות בהתנהגות ספציפית.

מופע Java של מפעיל

כדי לבדוק אם אובייקט נוצר על סמך מחלקה, יש אופרטור מיוחד ב-Java - instanceof. הוא מחזיר את הערך trueאם הבדיקה הייתה אמת, או falseאם התוצאה הייתה שקר. בואו נראה איך זה עובד תוך שימוש בשיעורי הרכב שלנו כדוגמה:
public class Truck extends Car {

   public static void main(String[] args) {

       Truck truck = new Truck();
       System.out.println(truck instanceof Car);
   }
}
פלט: נכון הצ'ק באמצעות האופרטור instanceofהחזיר true, מכיוון שיש לנו אובייקט של המחלקה Truck, וכל המשאיות הן מכוניות. הכיתה Truckהיא צאצא של הכיתה Car, לכן, כל המשאיות נוצרות על בסיס הורה משותף - מכונית. שימו לב לאופרטור instanceof: הוא כתוב ללא נקודה, מכיוון שהוא אופרטור, לא שיטה ("instance instanceof Class"). בואו ננסה את זה אחרת:
public static void main(String[] args) {

   Car car = new Car();
   System.out.println(car instanceof Truck);
}
פלט: false המחלקה Carובהתאם לכך האובייקט שלה אינם נובעים מהמחלקה Truck.כל המשאיות הן מכוניות, אך לא כל המכוניות הן משאיות. אובייקטים Carאינם נוצרים על סמך המחלקה Truck. עוד דוגמה אחת:
public static void main(String[] args) {

   Car car = new Car();
   Truck truck = new Truck();
   System.out.println(car instanceof Object && truck instanceof Object);
}
פלט: נכון גם ההיגיון כאן פשוט: כל המחלקות בג'אווה, כולל אלו שיצרת, מגיעות ממחלקה Object(למרות שלא כותבים בהן extends Object - המנגנון הזה מרומז בהם). מדוע זה עשוי להיות שימושי ובאילו נסיבות? השימוש הנפוץ ביותר באופרטור instanceofהוא כעקוף שיטה equals(). לדוגמה, כך מיושמת השיטה equalsבמחלקה String:
public boolean equals(Object anObject) {
   if (this == anObject) {
       return true;
   }
   if (anObject instanceof String) {
       String anotherString = (String) anObject;
       int n = value.length;
       if (n == anotherString.value.length) {
           char v1[] = value;
           char v2[] = anotherString.value;
           int i = 0;
           while (n-- != 0) {
               if (v1[i] != v2[i])
                       return false;
               i++;
           }
           return true;
       }
   }
   return false;
}
לפני השוואה בין המחרוזת לאובייקט שעבר, השיטה בודקת: האם האובייקט המועבר הוא בעצם מחרוזת? ורק אז הוא מתחיל להשוות בין מאפיינים של שני עצמים. ללא הסימון הזה, אתה יכול להעביר כל אובייקט שיש לו שדות ערך ואורך לתוך השיטה ולהשוות אותו עם מחרוזת, מה שכמובן יהיה שגוי.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION