

Animal
klasse hebben:
public class Animal {
String name;
int age;
}
We kunnen 2 kinderklassen declareren: Cat
en Dog
. Dit wordt gedaan met behulp van het trefwoord extends .
public class Cat extends Animal {
}
public class Dog extends Animal {
}
We kunnen dit in de toekomst nuttig vinden. Als er bijvoorbeeld een taak is om muizen te vangen, maken we een Cat
object in ons programma. Als het de taak is om achter een stok aan te jagen, dan gebruiken we een Dog
voorwerp. En als we een programma maken dat een dierenkliniek simuleert, werkt het met de Animal
klas (en kan het dus zowel katten als honden behandelen). Het is heel belangrijk om te onthouden dat wanneer een object wordt gemaakt, eerst de constructor van zijn basisklasse wordt aangeroepen . Pas nadat die constructor is voltooid, voert het programma de constructor uit van de klasse die overeenkomt met het object dat we maken. Met andere woorden, bij het maken van een Cat
object wordt eerst deAnimal
constructor uitgevoerd en pas daarna deCat
constructeur uitgevoerd . Om dit te zien, voegt u wat console-uitvoer toe aan de Cat
and- Animal
constructors.
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();
}
}
Console-uitvoer: Animal constructor uitgevoerd Cat constructor uitgevoerd! Zo werkt het inderdaad! Waarom? Eén reden is om te voorkomen dat velden die tussen de twee klassen worden gedeeld, worden gedupliceerd. Elk dier heeft bijvoorbeeld een hart en hersenen, maar niet elk dier heeft een staart. We zouden hersen- en hartvelden , die gemeenschappelijk zijn voor alle dieren, kunnen declareren in de Animal
ouderklasse, en een staartveld in de Cat
subklasse. . Nu declareren we een Cat
klassenconstructor die argumenten voor alle 3 de velden accepteert.
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");
}
}
Opmerking: de constructor werkt correct, ook al heeft de Cat
klasse geen hersen- en hartvelden . Deze velden zijn "geërfd" van de Animal
basisklasse. De overervende klasse heeft toegang tot de velden van de basisklasse , zodat ze zichtbaar zijn in onze Cat
klasse. Als gevolg hiervan hoeven we deze velden niet in de Cat
klas te dupliceren. We kunnen ze uit de klas halen Animal
. Bovendien kunnen we de constructor van de basisklasse expliciet aanroepen in de constructor van de onderliggende klasse. Een basisklasse wordt ook wel een " superklasse " genoemd. Daarom gebruikt Java het sleutelwoord super om de basisklasse aan te geven. In het vorige voorbeeld
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
We hebben elk veld afzonderlijk toegewezen in onze bovenliggende klasse. We hoeven dit eigenlijk niet te doen. Het volstaat om de constructor van de bovenliggende klasse aan te roepen en de nodige argumenten door te geven:
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");
}
}
In de Cat
constructor hebben we de Animal
constructor aangeroepen en twee velden doorgegeven. We hadden slechts één veld om expliciet te initialiseren: tail , wat niet in Animal
. Weet je nog dat we vermeldden dat de constructor van de bovenliggende klasse als eerste wordt aangeroepen wanneer een object wordt gemaakt? Daarom moet super() altijd de eerste zijn in een constructor! Anders wordt de constructorlogica geschonden en genereert het programma een fout.
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");
}
}
De compiler weet dat wanneer een object van een onderliggende klasse wordt gemaakt, eerst de constructor van de basisklasse wordt aangeroepen. En als u dit gedrag handmatig probeert te wijzigen, staat de compiler dit niet toe.
Hoe een object wordt gemaakt
We hebben eerder gekeken naar een voorbeeld met een basis- en bovenliggende klasse:Animal
en Cat
. Met deze twee klassen als voorbeelden, gaan we nu kijken naar het proces van het maken van een object en het initialiseren van variabelen. We weten dat er statische en instantie (niet-statische) variabelen zijn . We weten ook dat de Animal
basisklasse variabelen heeft en de Cat
onderliggende klasse zijn eigen. Voor de duidelijkheid voegen we elk één statische variabele toe aan de klassen Animal
and Cat
. De variabele animalCountAnimal
in de klasse vertegenwoordigt het totale aantal diersoorten op aarde en de catCountvariabele geeft het aantal kattensoorten aan. Bovendien zullen we startwaarden toewijzen aan alle niet-statische variabelen in beide klassen (die vervolgens worden gewijzigd in de constructor).
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");
}
}
We maken dus een nieuwe instantie van de Cat
klasse, die overerft Animal
. We hebben wat gedetailleerde console-uitvoer toegevoegd om te zien wat er gebeurt en in welke volgorde. Dit is wat wordt weergegeven wanneer een Cat
object wordt gemaakt: De constructor van de Animal-basisklasse draait. Zijn de variabelen van de Animal-klasse al geïnitialiseerd? Huidige waarde van statische variabele animalCount = 7700000 Huidige waarde van hersenen in de Animal-klasse = Beginwaarde van hersenen in de Animal-klasse Huidige waarde van hart in de Animal-klasse = Beginwaarde van hart in de Animal-klasse Beschikken al over de variabelen van de Cat-klasse geïnitialiseerd? Huidige waarde van statische variabele catCount = 37 Constructor basisklasse dier is klaar! Huidige waarde van hersenen = Hersenen Huidige waarde hart = Hart De cat class constructor is gestart (De Animal constructor is al klaar) Huidige waarde van statische variabele catCount = 37 Huidige waarde van staart = Beginwaarde van staart in de Cat klasse Huidige waarde van staart = Staart We kunnen nu dus duidelijk de volgorde zien van variabele initialisatie en constructoraanroepen wanneer een nieuw object wordt gemaakt:
- Statische variabelen van de basisklasse (
Animal
) worden geïnitialiseerd. In ons geval is de variabele animalCountAnimal
van de klasse ingesteld op 7700000. -
Statische variabelen van de onderliggende klasse (
Cat
) worden geïnitialiseerd.Opmerking: we zitten nog steeds in de
Animal
constructor en we hebben al weergegeven:De constructor van de Animal-basisklasse draait.
Zijn de variabelen van de Animal-klasse al geïnitialiseerd?
Huidige waarde van statische variabele animalCount = 7700000
Huidige waarde van hersenen in de Animal-klasse = Beginwaarde van hersenen in de Animal-klasse
Huidige waarde van hart in de Animal-klasse = Beginwaarde van hart in de Animal-klasse
Beschikken al over de variabelen van de Cat-klasse geïnitialiseerd?
Huidige waarde van statische variabele catCount = 37 -
Vervolgens worden de niet-statische variabelen van de basisklasse geïnitialiseerd. We hebben ze specifiek beginwaarden toegewezen, die vervolgens in de constructor worden vervangen. De Animal constructor is nog niet klaar, maar de beginwaarden van hersenen en hart zijn al toegewezen:
De constructor van de Animal-basisklasse draait.
Zijn de variabelen van de Animal-klasse al geïnitialiseerd?
Huidige waarde van statische variabele animalCount = 7700000
Huidige waarde van hersenen in de Animal-klasse = Beginwaarde van hersenen in de Animal-klasse
Huidige waarde van hart in de Animal-klasse = Beginwaarde van hart in de Animal-klasse -
De constructor van de basisklasse start.
We hebben onszelf er al van overtuigd dat deze stap de vierde is: in de eerste drie stappen aan het begin van deAnimal
constructor hebben al veel variabelen waarden gekregen. -
Niet-statische velden van de onderliggende klasse (
Cat
) worden geïnitialiseerd.
Dit gebeurt voordat deCat
constructor begint te lopen.
Wanneer het begint te lopen, heeft de variabele staart al een waarde:De constructor van de klasse cat is gestart (de constructor Animal is al voltooid) Huidige waarde van de statische variabele catCount = 37 Huidige waarde van staart = Beginwaarde van staart in de klasse Cat
-
De constructor van de
Cat
onderliggende klasse wordt aangeroepenEn zo ziet het maken van een object eruit in Java!
Ik moet zeggen dat we geen grote fans zijn van uit het hoofd leren, maar het is het beste om de volgorde van variabele initialisatie en constructoraanroepen te onthouden .
Dit zal uw begrip van de stroom van het programma en de toestand van uw objecten op een bepaald moment aanzienlijk vergroten.
Bovendien gebruiken veel klassen geen overerving. In dit geval zijn de stappen met betrekking tot de basisklasse niet van toepassing.
Meer lezen: |
---|
GO TO FULL VERSION