שלום! בפעם הקודמת דיברנו על קונסטרוקטורים , ולמדנו עליהם הרבה. עכשיו נדבר על דבר כזה כמו בנאי מחלקות בסיס. מהי מחלקה בסיסית ? העובדה היא שב-Java, למספר מחלקות שונות יכולות להיות מקור משותף. זה נקרא ירושה . למספר כיתות צאצאים יכולה להיות מעמד אב קדמון אחד משותף. לדוגמה, דמיינו שיש לנו כיתה
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
. כעת, באמצעות שתי המחלקות הללו כדוגמה, נבחן את תהליך יצירת האובייקט ואתחול המשתנים. אנו יודעים שמשתנים הם משתנים סטטיים ומשתני מופע (לא סטטיים). אנחנו גם יודעים שלמחלקת הבסיס יש משתנים משלה, ולמחלקה הצאצאית יש משלה. בואו נוסיף משתנה סטטי אחד למחלקה לצורך הבהירות . משתנה המחלקה יהיה המספר הכולל של מיני בעלי חיים על פני כדור הארץ, והמשתנה יהיה מספר מיני החתולים. בנוסף, נקצה ערכי התחלה לכל המשתנים הלא סטטיים של שתי המחלקות (אשר ישתנו לאחר מכן בבנאי). Animal
Cat
Animal
Cat
animalCount
Animal
catsCount
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 = Хвост
אז, כעת אנו יכולים לראות בבירור באיזה סדר אתחול משתנים ונקראים בנאים בעת יצירת אובייקט חדש:
-
משתנים סטטיים של מחלקת הבסיס ( ) מאותחלים
Animal
. במקרה שלנו, למשתנהanimalCount
המחלקהAnimal
נקבע הערך 7700000. -
המשתנים הסטטיים של המחלקה הצאצאית ( ) מאותחלים
Cat
. שימו לב - אנחנו עדיין בתוך הקונסטרוקטורAnimal
, והקונסולה כבר אומרת:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal Были ли уже проинициализированы переменные класса Cat? Текущее meaning статической переменной catsCount = 37
-
לאחר מכן, משתנים לא סטטיים של מחלקת הבסיס מאותחלים . הקצינו להם במיוחד ערכים ראשוניים, אשר משתנים לאחר מכן לערכים חדשים בבנאי. הבנאי
Animal
עדיין לא השלים את עבודתו, אבל הערכים ההתחלתייםbrain
כברheart
הוקצו:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее meaning статической переменной animalCount = 7700000 Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
-
בנאי מחלקות הבסיס מתחיל לעבוד .
כבר ראינו ששלב זה הוא רק הרביעי: בשלוש הנקודות הראשונות, בזמן שהקונסטרוקטור מתחיל לעבוד,
Animal
למשתנים רבים כבר הוקצו ערכים. -
אתחול שדות לא סטטיים של כיתת ילד (
Cat
).זה קורה לפני שהמעצב
Cat
מתחיל לעבוד.בזמן שהוא התחיל לעבוד, למשתנה
tail
כבר היה ערך:Конструктор класса Cat начал работу (конструктор Animal уже был выполнен) Текущее meaning статической переменной catsCount = 37 Текущее meaning tail = Изначальное meaning tail в классе Cat
-
הקונסטרוקטור של מחלקת הצאצא נקרא
Cat
GO TO FULL VERSION