

Animal
Klasse:
public class Animal {
String name;
int age;
}
Wir können zwei untergeordnete Klassen deklarieren: Cat
und Dog
. Dies geschieht mit dem Schlüsselwort „extends“ .
public class Cat extends Animal {
}
public class Dog extends Animal {
}
Möglicherweise finden wir dies in Zukunft hilfreich. Wenn es zum Beispiel eine Aufgabe gibt, Mäuse zu fangen, erstellen wir ein Cat
Objekt in unserem Programm. Wenn die Aufgabe darin besteht, einem Stock nachzujagen, verwenden wir einen Dog
Gegenstand. Und wenn wir ein Programm erstellen, das eine Tierklinik simuliert, funktioniert es mit der Animal
Klasse (und kann somit sowohl Katzen als auch Hunde behandeln). Es ist sehr wichtig, sich daran zu erinnern , dass beim Erstellen eines Objekts zuerst der Konstruktor seiner Basisklasse aufgerufen wird . Erst nachdem dieser Konstruktor abgeschlossen ist, führt das Programm den Konstruktor der Klasse aus, die dem von uns erstellten Objekt entspricht. Mit anderen Worten: Beim Erstellen eines Cat
Objekts wird zuerst derAnimal
Konstruktor ausgeführt und erst danachCat
Konstruktor ausgeführt . Cat
Um dies zu sehen, fügen Sie den und- Konstruktoren eine Konsolenausgabe hinzu 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();
}
}
Konsolenausgabe: Animal-Konstruktor ausgeführt Cat-Konstruktor ausgeführt! Tatsächlich funktioniert es so! Warum? Ein Grund besteht darin, die Duplizierung von Feldern zu vermeiden, die von den beiden Klassen gemeinsam genutzt werden. Beispielsweise hat jedes Tier ein Herz und ein Gehirn, aber nicht jedes Tier hat einen Schwanz. Wir könnten Gehirn- und Herzfelder , die allen Tieren gemeinsam sind, in der Animal
Elternklasse und ein Schwanzfeld in der Cat
Unterklasse deklarieren . . Jetzt deklarieren wir einen Cat
Klassenkonstruktor, der Argumente für alle drei Felder akzeptiert.
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");
}
}
Hinweis: Der Konstruktor funktioniert korrekt, auch wenn die Cat
Klasse keine Gehirn- und Herzfelder hat . Diese Felder werden von der Animal
Basisklasse „geerbt“. Die erbende Klasse hat Zugriff auf die Felder der BasisklasseCat
, sodass diese in unserer Klasse sichtbar sind . Daher müssen wir diese Felder in der Cat
Klasse nicht duplizieren. Wir können sie aus der Animal
Klasse mitnehmen. Darüber hinaus können wir den Basisklassenkonstruktor im untergeordneten Klassenkonstruktor explizit aufrufen. Eine Basisklasse wird auch „ Superklasse “ genannt. Aus diesem Grund verwendet Java das Schlüsselwort super , um die Basisklasse anzugeben. Im vorherigen Beispiel
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
Wir haben jedes Feld in unserer übergeordneten Klasse separat zugewiesen. Wir müssen das eigentlich nicht tun. Es reicht aus, den Konstruktor der übergeordneten Klasse aufzurufen und die erforderlichen Argumente 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("Brain", "Heart", "Tail");
}
}
Im Cat
Konstruktor haben wir den Animal
Konstruktor aufgerufen und zwei Felder übergeben. Wir mussten nur ein Feld explizit initialisieren: tail , das nicht in ist Animal
. Erinnern Sie sich, dass wir erwähnt haben, dass der Konstruktor der übergeordneten Klasse zuerst aufgerufen wird, wenn ein Objekt erstellt wird? Deshalb sollte super() in einem Konstruktor immer an erster Stelle stehen! Andernfalls wird die Konstruktorlogik verletzt 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);// Error!
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
Der Compiler weiß, dass beim Erstellen eines Objekts einer untergeordneten Klasse zuerst der Basisklassenkonstruktor aufgerufen wird. Und wenn Sie versuchen, dieses Verhalten manuell zu ändern, lässt der Compiler dies nicht zu.
Wie ein Objekt erstellt wird
Wir haben uns zuvor 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 es statische und Instanzvariablen (nicht statisch) gibt . Wir wissen auch, dass die Animal
Basisklasse Variablen hat und die Cat
untergeordnete Klasse ihre eigenen. Aus Gründen der Übersichtlichkeit fügen wir den Klassen Animal
und jeweils eine statische Variable hinzu Cat
. Die Variable animalCountAnimal
in der Klasse repräsentiert die Gesamtzahl der Tierarten auf der Erde und die Variable catCountDie Variable gibt die Anzahl der Katzenarten an. Darüber hinaus weisen wir allen nicht statischen Variablen in beiden Klassen Startwerte zu (die dann im Konstruktor geändert werden).
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");
}
}
Also erstellen wir eine neue Instanz der Cat
Klasse, die erbt Animal
. Wir haben eine detaillierte Konsolenausgabe hinzugefügt, um zu sehen, was passiert und in welcher Reihenfolge. Folgendes wird angezeigt, wenn ein Cat
Objekt erstellt wird: Der Konstruktor der Animal-Basisklasse wird ausgeführt. Wurden die Variablen der Animal-Klasse bereits initialisiert? Aktueller Wert der statischen Variablen animalCount = 7700000 Aktueller Wert von brain in der Animal-Klasse = Anfangswert von brain in der Animal-Klasse Aktueller Wert von heart in der Animal-Klasse = Anfangswert von heart in der Animal-Klasse Die Variablen der Cat-Klasse sind bereits vorhanden wurde initialisiert? Aktueller Wert der statischen Variablen catCount = 37 Der Konstruktor der Tier-Basisklasse ist fertig! Aktueller Wert von brain = Brain Aktueller Wert heart = Heart Der Cat-Klassenkonstruktor wurde gestartet (Der Animal-Konstruktor ist bereits fertig) Aktueller Wert der statischen Variablen catCount = 37 Aktueller Wert von tail = Anfangswert von tail in der Cat-Klasse Aktueller Wert von tail = Schwanz Jetzt können wir die Reihenfolge der Variableninitialisierung und der Konstruktoraufrufe beim Erstellen eines neuen Objekts klar erkennen:
- Statische Variablen der Basisklasse (
Animal
) werden initialisiert. In unserem Fall ist die Variable animalCountAnimal
der Klasse auf 7700000 gesetzt. -
Statische Variablen der untergeordneten Klasse (
Cat
) werden initialisiert.Hinweis: Wir befinden uns noch im
Animal
Konstruktor und haben bereits Folgendes angezeigt:Der Konstruktor der Animal-Basisklasse wird ausgeführt.
Wurden die Variablen der Animal-Klasse bereits initialisiert?
Aktueller Wert der statischen Variablen animalCount = 7700000
Aktueller Wert von brain in der Animal-Klasse = Anfangswert von brain in der Animal-Klasse
Aktueller Wert von heart in der Animal-Klasse = Anfangswert von heart in der Animal-Klasse
Die Variablen der Cat-Klasse sind bereits vorhanden wurde initialisiert?
Aktueller Wert der statischen Variablen catCount = 37 -
Anschließend werden die nicht statischen Variablen der Basisklasse initialisiert. Wir haben ihnen gezielt Anfangswerte zugewiesen, die dann im Konstruktor ersetzt werden. Der Animal-Konstruktor ist noch nicht fertig, aber die Anfangswerte von brain und heart wurden bereits zugewiesen:
Der Konstruktor der Animal-Basisklasse wird ausgeführt.
Wurden die Variablen der Animal-Klasse bereits initialisiert?
Aktueller Wert der statischen Variablen animalCount = 7700000
Aktueller Wert von Gehirn in der Klasse „Tier“ = Anfangswert von Gehirn in der Klasse „Tier“
Aktueller Wert von Herz in der Klasse „Tier“ = Anfangswert von Herz in der Klasse „Tier“. -
Der Basisklassenkonstruktor wird gestartet.
Wir haben uns bereits davon überzeugt, dass dieser Schritt der vierte ist: In den ersten drei Schritten am Anfang desAnimal
Konstruktors wurden vielen Variablen bereits Werte zugewiesen. -
Nicht statische Felder der untergeordneten Klasse (
Cat
) werden initialisiert.
Dies geschieht, bevor derCat
Konstruktor ausgeführt wird.
Wenn die Ausführung beginnt, hat die Variable tail bereits einen Wert:Der Cat-Klassenkonstruktor wurde gestartet (Der Animal-Konstruktor ist bereits fertig). Aktueller Wert der statischen Variablen catCount = 37 Aktueller Wert von tail = Anfangswert von tail in der Cat-Klasse
-
Der Konstruktor der
Cat
untergeordneten Klasse wird aufgerufenUnd so sieht das Erstellen eines Objekts in Java aus!
Ich muss sagen, dass wir keine großen Fans des Auswendiglernens sind, aber es ist am besten, sich die Reihenfolge der Variableninitialisierung und der Konstruktoraufrufe zu merken .
Dies wird Ihr Verständnis des Programmablaufs und des Zustands Ihrer Objekte zu jedem bestimmten Zeitpunkt erheblich verbessern.
Darüber hinaus verwenden viele Klassen keine Vererbung. In diesem Fall gelten die Schritte im Zusammenhang mit der Basisklasse nicht.
Mehr Lektüre: |
---|
GO TO FULL VERSION