Animal
(Tier):
public class Animal {
String name;
int age;
}
Wir können dafür zum Beispiel 2 Nachkommenklassen erstellen – Cat
und Dog
. Dies geschieht mit dem Schlüsselwort extends
.
public class Cat extends Animal {
}
public class Dog extends Animal {
}
Dies könnte für uns in Zukunft nützlich sein. Wenn die Aufgabe beispielsweise darin besteht, Mäuse zu fangen, erstellen wir im Programm ein Objekt Cat
. Wenn die Aufgabe darin besteht, einem Stick nachzulaufen, dann verwenden wir das Objekt Dog
. Und wenn wir ein Programm erstellen, das eine Tierklinik simuliert, funktioniert es mit der Klasse Animal
(um sowohl Katzen als auch Hunde behandeln zu können). Es ist sehr wichtig, sich für die Zukunft daran zu erinnern, dass beim Erstellen eines Objekts zuerst der Konstruktor seiner Basisklasse und erst dann der Konstruktor der Klasse selbst aufgerufen wird, deren Objekt wir erstellen. Das heißt, beim Erstellen eines Objekts Cat
arbeitet zuerst der Klassenkonstruktor Animal
und erst dann der Konstruktor Cat
. Um dies sicherzustellen, ergänzen wir die Konstruktoren Cat
und Animal
geben sie auf der Konsole aus.
public class Animal {
public Animal() {
System.out.println(„Tierkonstrukteur abgeschlossen“);
}
}
public class Cat extends Animal {
public Cat() {
System.out.println(„Der Konstrukteur Cat hat funktioniert!“);
}
public static void main(String[] args) {
Cat cat = new Cat();
}
}
Konsolenausgabe:
Отработал конструктор Animal
Отработал конструктор Cat!
Tatsächlich funktioniert das Ganze so! Wofür ist das? Um beispielsweise die Duplizierung gemeinsamer Felder zweier Klassen zu vermeiden. Beispielsweise hat jedes Tier ein Herz und ein Gehirn, aber nicht jedes Tier hat einen Schwanz. Wir können Felder, die allen Tieren gemeinsam sind, brain
in heart
der übergeordneten Klasse Animal
und ein Feld tail
in der Unterklasse deklarieren Cat
. Jetzt erstellen wir einen Konstruktor für die Klasse Cat
, in dem wir alle drei Felder übergeben.
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("Gehirn", "Herz", "Schwanz");
}
}
Passt auf:Der Konstruktor funktioniert erfolgreich, obwohl die Klasse Cat
keine Felder brain
und hat heart
. Diese Felder wurden aus der Basisklasse „heraufgezogen“ Animal
. Die Nachkommenklasse hat Zugriff auf die Felder der Basisklasse, sodass Cat
diese in unserer Klasse sichtbar sind. Daher müssen wir diese Felder nicht Cat
in der Klasse duplizieren – wir können sie aus der Klasse übernehmen Animal
. Darüber hinaus können wir den Konstruktor der Basisklasse explizit im Konstruktor der Nachkommenklasse aufrufen. Die Basisklasse wird auch „ Superklasse “ genannt, weshalb Java das Schlüsselwort verwendet super
. Im vorherigen Beispiel
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
Wir haben jedes Feld, das sich in unserer übergeordneten Klasse befindet, separat zugewiesen. Tatsächlich müssen Sie dies nicht tun. Es genügt, den Konstruktor der übergeordneten Klasse aufzurufen und ihm die notwendigen Parameter zu übergeben:
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("Gehirn", "Herz", "Schwanz");
}
}
Im Konstruktor Cat
haben wir den Konstruktor aufgerufen Animal
und ihm zwei Felder übergeben. Wir müssen nur ein Feld explizit initialisieren – tail
das Animal
nicht vorhanden ist. Erinnern Sie sich, wie wir gesagt haben, dass beim Erstellen eines Objekts zuerst der Konstruktor der übergeordneten Klasse aufgerufen wird? Deshalb super()
sollte das Wort im Konstruktor immer an erster Stelle stehen! Andernfalls wird die Logik der Konstruktoren beschädigt und das Programm generiert einen Fehler.
public class Cat extends Animal {
String tail;
public Cat(String brain, String heart, String tail) {
this.tail = tail;
super(brain, heart);//Fehler!
}
public static void main(String[] args) {
Cat cat = new Cat("Gehirn", "Herz", "Schwanz");
}
}
Der Compiler weiß, dass beim Erstellen eines Objekts einer Nachfolgeklasse zuerst der Konstruktor der Basisklasse aufgerufen wird. Und wenn Sie versuchen, dieses Verhalten manuell zu ändern, wird dies nicht zugelassen.
Der Prozess der Erstellung eines Objekts.
Oben haben wir uns ein Beispiel mit einer Basis- und einer übergeordneten Klasse angesehen –Animal
und Cat
. Am Beispiel dieser beiden Klassen betrachten wir nun den Prozess der Objekterstellung und Initialisierung von Variablen. Wir wissen, dass Variablen statische und Instanzvariablen (nicht statisch) sind. Wir wissen auch, dass die Basisklasse Animal
ihre eigenen Variablen hat und die Nachkommenklasse Cat
ihre eigenen. Fügen wir der Klasse aus Gründen der Animal
Übersichtlichkeit eine statische Variable hinzu . Cat
Die Klassenvariable wäre die Gesamtzahl der Tierarten auf der Erde und die Variable animalCount
wäre die Zahl der Katzenarten. Darüber hinaus werden wir allen nicht statischen Variablen beider Klassen Startwerte zuweisen (die sich dann im Konstruktor ändern). Animal
catsCount
public class Animal {
String brain = „Der anfängliche Wert des Gehirns in der Tierklasse“;
String heart = „Der Anfangswert des Herzens in der Tierklasse“;
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println(„Der Konstruktor der Animal-Basisklasse wird ausgeführt“);
System.out.println(„Wurden die Variablen der Animal-Klasse bereits initialisiert?“);
System.out.println(„Der aktuelle Wert der statischen Variablen animalCount =“ + animalCount);
System.out.println(„Aktueller Wert des Gehirns in der Klasse Tier =“ + this.brain);
System.out.println(„Aktueller Wert des Herzens in der Klasse Tier =“ + this.heart);
System.out.println(„Sind die Variablen der Cat-Klasse bereits initialisiert?“);
System.out.println(„Der aktuelle Wert der statischen Variablen catsCount =“ + Cat.catsCount);
this.brain = brain;
this.heart = heart;
System.out.println(„Animal-Basisklassenkonstruktor abgeschlossen!“);
System.out.println(„Aktueller Wert des Gehirns =“ + this.brain);
System.out.println(„Aktueller Wert des Herzens =“ + this.heart);
}
}
public class Cat extends Animal {
String tail = „Der Anfangswert von tail in der Cat-Klasse“;
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println(„Der Konstruktor der Cat-Klasse wurde gestartet (der Animal-Konstruktor wurde bereits ausgeführt)“);
System.out.println(„Der aktuelle Wert der statischen Variablen catsCount =“ + catsCount);
System.out.println(„Aktueller Wert tail =“ + this.tail);
this.tail = tail;
System.out.println(„Aktueller Wert tail =“ + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Gehirn", "Herz", "Schwanz");
}
}
Also erstellen wir ein neues Objekt der Cat
von geerbten Klasse Animal
. Fügen wir unserem Programm eine detaillierte Konsolenausgabe hinzu, um zu sehen, was passieren wird und in welcher Reihenfolge. Folgendes wird als Ergebnis der Objekterstellung an die Konsole ausgegeben Cat
:
Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее Bedeutung статической переменной animalCount = 7700000
Текущее Bedeutung brain в классе Animal = Изначальное Bedeutung brain в классе Animal
Текущее Bedeutung heart в классе Animal = Изначальное Bedeutung heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее Bedeutung статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее Bedeutung brain = Мозг
Текущее Bedeutung heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее Bedeutung статической переменной catsCount = 37
Текущее Bedeutung tail = Изначальное Bedeutung tail в классе Cat
Текущее Bedeutung tail = Хвост
Jetzt können wir deutlich erkennen, in welcher Reihenfolge Variablen initialisiert und Konstruktoren aufgerufen werden, wenn ein neues Objekt erstellt wird:
-
Statische Variablen der Basisklasse ( ) werden initialisiert
Animal
. In unserem Fall wird deranimalCount
KlassenvariablenAnimal
der Wert 7700000 zugewiesen. -
Die statischen Variablen der Nachkommenklasse ( ) werden initialisiert
Cat
. Achtung – wir befinden uns noch im KonstruktorAnimal
und die Konsole sagt bereits:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее Bedeutung статической переменной animalCount = 7700000 Текущее Bedeutung brain в классе Animal = Изначальное Bedeutung brain в классе Animal Текущее Bedeutung heart в классе Animal = Изначальное Bedeutung heart в классе Animal Были ли уже проинициализированы переменные класса Cat? Текущее Bedeutung статической переменной catsCount = 37
-
Als nächstes werden nicht statische Variablen der Basisklasse initialisiert . Wir haben ihnen gezielt Anfangswerte zugewiesen, die dann im Konstruktor in neue geändert werden. Der Konstruktor
Animal
hat seine Arbeit noch nicht abgeschlossen, aber die Anfangswertebrain
wurdenheart
bereits zugewiesen:Выполняется конструктор базового класса Animal Были ли уже проинициализированы переменные класса Animal? Текущее Bedeutung статической переменной animalCount = 7700000 Текущее Bedeutung brain в классе Animal = Изначальное Bedeutung brain в классе Animal Текущее Bedeutung heart в классе Animal = Изначальное Bedeutung heart в классе Animal
-
Der Basisklassenkonstruktor beginnt zu arbeiten .
Wir haben bereits gesehen, dass dieser Schritt erst der vierte ist: In den ersten drei Punkten sind zu dem Zeitpunkt, an dem der Konstruktor seine Arbeit aufnimmt,
Animal
vielen Variablen bereits Werte zugewiesen. -
Initialisieren nicht statischer Felder einer untergeordneten Klasse (
Cat
).Dies geschieht, bevor der Designer
Cat
mit der Arbeit beginnt.Als er mit der Arbeit begann,
tail
hatte die Variable bereits einen Wert:Конструктор класса Cat начал работу (конструктор Animal уже был выполнен) Текущее Bedeutung статической переменной catsCount = 37 Текущее Bedeutung tail = Изначальное Bedeutung tail в классе Cat
-
Der Konstruktor der Nachkommenklasse wird aufgerufen
Cat
GO TO FULL VERSION