JavaRush /בלוג Java /Random-HE /בוני מחלקות בסיס

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

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

   String name;
   int age;
}
אנחנו יכולים ליצור עבורו, למשל, 2 כיתות צאצאים - Catו Dog. זה נעשה באמצעות מילת המפתח extends.
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 completed");
   }
}


public class Cat extends Animal {

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

   public static void main(String[] args) {
       Cat cat = new Cat();
   }
}
פלט מסוף:

Отработал конструктор Animal
Отработал конструктор Cat!
ואכן, כך הכל עובד! לשם מה זה? לדוגמה, כדי להימנע משכפול שדות משותפים של שתי מחלקות. למשל, לכל חיה יש לב ומוח, אבל לא לכל חיה יש זנב. אנו יכולים להכריז על שדות משותפים לכל בעלי החיים brainבמחלקת heartהאב Animal, ועל שדה tailבתת המחלקה Cat. כעת ניצור קונסטרוקטור עבור המחלקה Cat, שם נעביר את כל 3 השדות.
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אין שדות brainו- heart. שדות אלה "נמשכו" ממחלקת הבסיס 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קיים. זוכרים איך אמרנו שכאשר נוצר אובייקט, הבנאי של מחלקת האב נקרא ראשון? לכן, זו הסיבה שהמילה super()צריכה להיות תמיד ראשונה בקונסטרוקטור! אחרת, הלוגיקה של הבנאים תישבר והתוכנית תיצור שגיאה.
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. כעת, באמצעות שתי המחלקות הללו כדוגמה, נבחן את תהליך יצירת האובייקט ואתחול המשתנים. אנו יודעים שמשתנים הם משתנים סטטיים ומשתני מופע (לא סטטיים). אנחנו גם יודעים שלמחלקת הבסיס יש משתנים משלה, ולמחלקה הצאצאית יש משלה. בואו נוסיף משתנה סטטי אחד למחלקה לצורך הבהירות . משתנה המחלקה יהיה המספר הכולל של מיני בעלי חיים על פני כדור הארץ, והמשתנה יהיה מספר מיני החתולים. בנוסף, נקצה ערכי התחלה לכל המשתנים הלא סטטיים של שתי המחלקות (אשר ישתנו לאחר מכן בבנאי). AnimalCatAnimalCatanimalCountAnimalcatsCount
public class Animal {

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

   public static int animalCount = 7700000;

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

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor completed!");
       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 = "The initial value of tail in the Cat class";

   static int catsCount = 37;

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

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

Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее meaning статической переменной animalCount = 7700000
Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее meaning статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее meaning brain = Мозг
Текущее meaning heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее meaning статической переменной catsCount = 37
Текущее meaning tail = Изначальное meaning tail в классе Cat
Текущее meaning tail = Хвост
אז, כעת אנו יכולים לראות בבירור באיזה סדר אתחול משתנים ונקראים בנאים בעת יצירת אובייקט חדש:
  1. משתנים סטטיים של מחלקת הבסיס ( ) מאותחלים Animal. במקרה שלנו, למשתנה animalCountהמחלקה Animalנקבע הערך 7700000.

  2. המשתנים הסטטיים של המחלקה הצאצאית ( ) מאותחלים Cat. שימו לב - אנחנו עדיין בתוך הקונסטרוקטור Animal, והקונסולה כבר אומרת:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее meaning статической переменной catsCount = 37
  3. לאחר מכן, משתנים לא סטטיים של מחלקת הבסיס מאותחלים . הקצינו להם במיוחד ערכים ראשוניים, אשר משתנים לאחר מכן לערכים חדשים בבנאי. הבנאי Animalעדיין לא השלים את עבודתו, אבל הערכים ההתחלתיים brainכבר heartהוקצו:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
  4. בנאי מחלקות הבסיס מתחיל לעבוד .

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

  5. אתחול שדות לא סטטיים של כיתת ילד ( Cat).

    זה קורה לפני שהמעצב Catמתחיל לעבוד.

    בזמן שהוא התחיל לעבוד, למשתנה tailכבר היה ערך:

    
    Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
    Текущее meaning статической переменной catsCount = 37
    Текущее meaning tail = Изначальное meaning tail в классе Cat
  6. הקונסטרוקטור של מחלקת הצאצא נקרא Cat

כך נראה תהליך יצירת אובייקט בג'אווה! אני חייב לומר שאנחנו לא מעריצים גדולים של דחיסה, אבל עדיף לשנן את סדר האתחול של משתנים וקריאה לבנאים ולזכור אותם לעתיד . זה יגדיל מאוד את ההבנה שלך לגבי התקדמות התוכנית ומצב האובייקטים שלך בכל רגע נתון. יתרה מכך, לשיעורים לרוב אין כיתות הורה ישירות (כיתות-על/כיתות בסיס). במקרה זה, הפריטים המשויכים למחלקת הבסיס לא יבוצעו.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION