CodeGym /בלוג Java /Random-HE /בוני מחלקות בסיס
John Squirrels
רָמָה
San Francisco

בוני מחלקות בסיס

פורסם בקבוצה
היי! בפעם הקודמת דיברנו על קונסטרוקטורים ולמדנו עליהם הרבה. עכשיו אנחנו הולכים לדבר על בנאים של מחלקות בסיס .
בוני מחלקות בסיס - 1
מהי מחלקה בסיסית ? זה קשור לעובדה שב-Java לכמה מחלקות שונות יכולות להיות מקור משותף.
בוני מחלקות בסיס - 2
זה נקרא ירושה . למספר כיתות ילדים יכול להיות אב קדמון אחד משותף. לדוגמה, דמיינו שיש לנו Animalמחלקה:
public class Animal {

   String name;
   int age;
}
אנו יכולים להכריז על 2 כיתות ילדים: Catו Dog. זה נעשה באמצעות מילת המפתח מרחיב .
public class Cat extends Animal {

}

public class Dog extends Animal {

}
זה עשוי להיות מועיל בעתיד. לדוגמה, אם יש משימה לתפוס עכברים, ניצור אובייקט Cat בתוכנית שלנו. אם המשימה היא לרדוף אחרי מקל, אז נשתמש בחפץ Dog . ואם ניצור תוכנית המדמה מרפאה וטרינרית, היא תעבוד עם Animal הכיתה (ובכך תוכל לטפל גם בחתולים וגם בכלבים). חשוב מאוד לזכור שכאשר אובייקט נוצר, הבנאי של מחלקת הבסיס שלו נקרא תחילה . רק לאחר סיום הבנאי, התוכנית מבצעת את הבנאי של המחלקה התואמת לאובייקט שאנו יוצרים. במילים אחרות, בעת יצירת Catאובייקט, הבנאי Animalמופעל תחילה ורק לאחר מכן Catמבוצע הבנאי . כדי לראות זאת, הוסף פלט מסוף לבנאי Catו Animal.
public class Animal {

   public Animal() {
       System.out.println("Animal constructor executed");
   }
}


public class Cat extends Animal {

   public Cat() {
       System.out.println("Cat constructor executed!");
   }

   public static void main(String[] args) {
       Cat cat = new Cat();
   }
}
פלט קונסולה: בונה בעלי חיים הוצא להורג בנאי חתול הוצא להורג! אכן, זה עובד ככה! למה? אחת הסיבות היא להימנע משכפול שדות משותפים בין שתי המחלקות. לדוגמה, לכל חיה יש לב ומוח, אבל לא לכל חיה יש זנב. נוכל להכריז על שדות מוח ולב , המשותפים לכל בעלי החיים, במחלקת האב, ושדה זנב בתת המעמד . . כעת נכריז על בנאי מחלקה שלוקח ארגומנטים עבור כל 3 השדות. AnimalCatCat
public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
הערה: הבנאי פועל כהלכה למרות שלמחלקה Catאין שדות מוח ולב . שדות אלה "עברו בירושה" ממחלקת Animalהבסיס. למחלקה היורשת יש גישה לשדות של מחלקת הבסיס , כך שהם גלויים במחלקה שלנו Cat. כתוצאה מכך, איננו צריכים לשכפל שדות אלה בכיתה Cat. אנחנו יכולים לקחת אותם מהכיתה Animal. מה שכן, אנו יכולים לקרוא במפורש לבנאי מחלקות הבסיס בבנאי מחלקות הילד. מחלקה בסיסית נקראת גם " מחלקה על ". זו הסיבה ש-Java משתמשת במילת המפתח super כדי לציין את מחלקת הבסיס. בדוגמה הקודמת
public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }
הקצינו בנפרד כל שדה בכיתת ההורים שלנו. אנחנו בעצם לא צריכים לעשות את זה. מספיק לקרוא לבנאי מחלקת האב ולהעביר את הטיעונים הדרושים:
public class Animal {

   String brain;
   String heart;

   public Animal(String brain, String heart) {
       this.brain = brain;
       this.heart = heart;
   }

public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       this.tail = tail;
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
בקונסטרוקטור Catקראנו לקונסטרוקטור Animalועברנו שני שדות. היה לנו רק שדה אחד לאתחל במפורש: tail , שאינו ב- Animal. זוכרים שהזכרנו שבנאי מחלקת האב נקרא ראשון כאשר אובייקט נוצר? זו הסיבה שסופר() תמיד צריך להיות ראשון בקונסטרוקטור! אחרת, הלוגיקה של הבנאי תופר והתוכנית תיצור שגיאה.
public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       this.tail = tail;
       super(brain, heart);// Error!
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
המהדר יודע שכאשר נוצר אובייקט של מחלקת ילד, הבנאי מחלקות הבסיס נקרא ראשון. ואם תנסה לשנות התנהגות זו באופן ידני, המהדר לא יאפשר זאת.

איך נוצר אובייקט

הסתכלנו בעבר על דוגמה עם כיתת בסיס והורה: Animalו Cat. באמצעות שתי המחלקות הללו כדוגמאות, כעת נסתכל על תהליך יצירת אובייקט ואתחול משתנים. אנו יודעים שיש משתנים סטטיים ומשתנים מופעיים (לא סטטיים) . אנחנו גם יודעים שלמחלקת Animalהבסיס יש משתנים, ולמחלקת Catהילד יש משלה. למען הבהירות, נוסיף משתנה סטטי אחד כל אחד למחלקות Animalו Cat. המשתנה animalCount במחלקה ייצג את המספר הכולל של מיני בעלי חיים על פני כדור הארץ, והמשתנה catCount יסמן את מספר מיני החתולים. בנוסף, נקצה ערכי התחלה לכל המשתנים הלא סטטיים בשתי המחלקות (אשר ישתנו לאחר מכן בבנאי). Animal
public class Animal {

   String brain = "Initial value of brain in the Animal class";
   String heart = "Initial value of heart in the Animal class";

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println("Animal base class constructor is running");
       System.out.println("Have the variables of the Animal class already been initialized?");
       System.out.println("Current value of static variable animalCount = " + animalCount);
       System.out.println("Current value of brain in the Animal class = " + this.brain);
       System.out.println("Current value of heart in the Animal class = " + this.heart);
       System.out.println("Have the variables of the Cat class already been initialized?");
       System.out.println("Current value of static variable catCount = " + Cat.catCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor is done!");
       System.out.println("Current value of brain = " + this.brain);
       System.out.println("Current value of heart = " + this.heart);
   }
}

public class Cat extends Animal {

   String tail = "Initial value of tail in the Cat class";

   static int catCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println("The cat class constructor has started (The Animal constructor already finished)");
       System.out.println("Current value of static variable catCount = " + catCount);
       System.out.println("Current value of tail = " + this.tail);
       this.tail = tail;
       System.out.println("Current value of tail = " + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
אז אנחנו יוצרים מופע חדש של המחלקה Cat, שיורש Animal. הוספנו פלט מפורט של המסוף כדי לראות מה קורה ובאיזה סדר. זה מה שיוצג בעת Catיצירת אובייקט: בנאי מחלקות בעלי חיים פועל האם המשתנים של מחלקת ה- Animal כבר אותחלו? ערך נוכחי של משתנה סטטי animalCount = 7700000 ערך נוכחי של מוח במחלקה Animal = ערך התחלתי של מוח במחלקת Animal ערך נוכחי של לב במחלקת Animal = ערך התחלתי של לב במחלקת Animal יש כבר את המשתנים של מחלקת Cat אותחל? ערך נוכחי של משתנה סטטי catCount = 37 הבנאי מחלקות בסיס בעלי חיים נעשה! ערך נוכחי של מוח = מוח ערך נוכחי לב = לב בנאי מחלקת החתול התחיל (בנאי החיות כבר הסתיים) ערך נוכחי של משתנה סטטי catCount = 37 ערך נוכחי של זנב = ערך התחלתי של זנב במחלקה חתול ערך נוכחי של זנב = זנב אז, כעת אנו יכולים לראות בבירור את סדר האתחול המשתנים וקריאות הבנאים כאשר אובייקט חדש נוצר:
  1. משתנים סטטיים של מחלקת הבסיס ( Animal) מאותחלים. במקרה שלנו, Animalהמשתנה animalCount של המחלקה מוגדר ל-7700000.

  2. משתנים סטטיים של מחלקת הילד ( Cat) מאותחלים.

    הערה: אנחנו עדיין בתוך Animalהבנאי וכבר הצגנו:

    בונה מחלקות בסיס בעלי חיים פועל
    האם המשתנים של מחלקת החיות כבר אותחלו?
    ערך נוכחי של משתנה סטטי animalCount = 7700000
    ערך נוכחי של מוח במחלקה Animal = ערך התחלתי של מוח במחלקת Animal ערך
    נוכחי של לב במחלקת Animal = ערך התחלתי של לב במחלקת Animal
    יש כבר את המשתנים של מחלקת Cat אותחל?
    ערך נוכחי של משתנה סטטי catCount = 37


  3. לאחר מכן מאותחלים המשתנים הלא סטטיים של מחלקת הבסיס . הקצינו להם במיוחד ערכים ראשוניים, שמוחלפים לאחר מכן בבנאי. בונה החיות עדיין לא סיים, אבל הערכים ההתחלתיים של המוח והלב כבר הוקצו:

    בונה מחלקות בסיס בעלי חיים פועל
    האם המשתנים של מחלקת החיות כבר אותחלו?
    ערך נוכחי של משתנה סטטי animalCount = 7700000
    ערך נוכחי של מוח במחלקת בעלי חיים = ערך התחלתי של מוח במחלקת בעלי חיים ערך
    נוכחי של לב במחלקת בעלי חיים = ערך התחלתי של לב במחלקת בעלי חיים


  4. הבנאי מחלקות הבסיס מתחיל.
    כבר שכנענו את עצמנו שהשלב הזה הוא רביעי: בשלושת השלבים הראשונים בתחילת הבנאי Animal, למשתנים רבים כבר הוקצו ערכים.


  5. שדות לא סטטיים של כיתת הילד ( Cat) מאותחלים.
    זה קורה לפני שהקונסטרוקטור Catמתחיל לפעול.
    כאשר הוא מתחיל לפעול, למשתנה הזנב כבר יש ערך:

    בנאי מחלקות החתול התחיל (בנאי החיות כבר הסתיים) ערך נוכחי של משתנה סטטי catCount = 37 ערך נוכחי של זנב = ערך התחלתי של זנב במחלקה Cat


  6. הקונסטרוקטור של Catכיתת הילד נקרא

    וכך נראית יצירת אובייקט בג'אווה!

    אני חייב לומר שאנחנו לא מעריצים גדולים של לימוד רוטינה, אבל עדיף לשנן את סדר האתחול המשתנים וקריאות הבנאים .

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

    יתר על כן, שיעורים רבים אינם משתמשים בירושה. במקרה זה, השלבים הקשורים למחלקת הבסיס אינם חלים.

הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION