

Animal
klasse:
public class Animal {
String name;
int age;
}
Vi kan erklære 2 barneklasser: Cat
og Dog
. Dette gjøres ved å bruke nøkkelordet extends .
public class Cat extends Animal {
}
public class Dog extends Animal {
}
Vi kan finne dette nyttig i fremtiden. For eksempel, hvis det er en oppgave å fange mus, lager vi et Cat
objekt i programmet vårt. Hvis oppgaven er å jage etter en pinne, så bruker vi en Dog
gjenstand. Og hvis vi lager et program som simulerer en veterinærklinikk, vil det fungere med Animal
klassen (og dermed kunne behandle både katter og hunder). Det er veldig viktig å huske at når et objekt opprettes, kalles først konstruktøren av dens basisklasse . Først etter at konstruktøren er ferdig, kjører programmet konstruktøren til klassen som tilsvarer objektet vi lager. Med andre ord, når du oppretter et Cat
objekt, kjøres konstruktøren først ,Animal
og først etterpå kjøresCat
konstruktør utført . For å se dette, legg til noe konsollutgang til Cat
og Animal
konstruktørene.
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();
}
}
Konsollutgang: Dyrekonstruktør utført Cat-konstruktør utført! Faktisk fungerer det slik! Hvorfor? En grunn er å unngå duplisering av felt som deles mellom de to klassene. For eksempel har hvert dyr et hjerte og en hjerne, men ikke alle dyr har en hale. Vi kunne erklære hjerne- og hjertefelt , som er felles for alle dyr, i foreldreklassen Animal
, og et halefelt i Cat
underklassen. . Nå skal vi erklære en Cat
klassekonstruktør som tar argumenter for alle 3 feltene.
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");
}
}
Merk: Konstruktøren fungerer riktig selv om klassen Cat
ikke har noen hjerne- og hjertefelt . Disse feltene er "arvet" fra Animal
basisklassen. Den arvende klassen har tilgang til feltene til basisklassen , så de er synlige i Cat
klassen vår. Som et resultat trenger vi ikke å duplisere disse feltene i Cat
klassen. Vi kan ta dem fra Animal
klassen. Dessuten kan vi eksplisitt kalle basisklassekonstruktøren i barneklassekonstruktøren. En basisklasse kalles også en " superklasse ". Det er derfor Java bruker nøkkelordet super for å indikere grunnklassen. I forrige eksempel
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
Vi tildelte hvert felt separat i foreldreklassen vår. Vi trenger faktisk ikke å gjøre dette. Det er nok å kalle den overordnede klassekonstruktøren og sende de nødvendige argumentene:
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");
}
}
I Cat
konstruktøren ringte vi konstruktøren Animal
og passerte to felt. Vi hadde bare ett felt å eksplisitt initialisere: tail , som ikke er i Animal
. Husker vi at vi nevnte at den overordnede klassekonstruktøren kalles først når et objekt opprettes? Derfor bør super() alltid være først i en konstruktør! Ellers vil konstruktørlogikken bli brutt og programmet vil generere en feil.
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");
}
}
Kompilatoren vet at når et objekt av en barneklasse opprettes, kalles basisklassekonstruktøren først. Og hvis du prøver å endre denne oppførselen manuelt, vil ikke kompilatoren tillate det.
Hvordan et objekt lages
Vi har tidligere sett på et eksempel med en base og overordnet klasse:Animal
og Cat
. Ved å bruke disse to klassene som eksempler, skal vi nå se på prosessen med å lage et objekt og initialisere variabler. Vi vet at det er statiske og instansvariabler (ikke-statiske) . Vi vet også at Animal
grunnklassen har variabler, og Cat
barneklassen har sine egne. For klarhetens skyld legger vi til én statisk variabel hver til klassene Animal
og Cat
. AnimalCount - variabelen i Animal
klassen vil representere det totale antallet dyrearter på jorden, og catCountvariabel vil angi antall kattearter. I tillegg vil vi tilordne startverdier til alle ikke-statiske variabler i begge klassene (som da vil bli endret i konstruktøren).
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");
}
}
Så vi oppretter en ny forekomst av Cat
klassen, som arver Animal
. Vi har lagt til noen detaljerte konsoller for å se hva som skjer og i hvilken rekkefølge. Dette er hva som vises når et Cat
objekt opprettes: Animal base class constructor kjører Har variablene til Animal-klassen allerede blitt initialisert? Gjeldende verdi av statisk variabel animalCount = 7700000 Gjeldende verdi av hjernen i dyreklassen = Startverdien av hjernen i dyreklassen Nåværende verdi på hjertet i dyreklassen = Startverdien til hjertet i dyreklassen Har variablene til katteklassen allerede blitt initialisert? Gjeldende verdi av statisk variabel catCount = 37 Dyrebaseklassekonstruktør er ferdig! Gjeldende verdi av hjerne = Hjerne Gjeldende verdi hjerte = Hjerte Katteklassekonstruktøren har startet (Dyrekonstruktøren er allerede ferdig) Gjeldende verdi av statisk variabel catCount = 37 Gjeldende verdi av hale = Startverdi av hale i Cat-klassen Gjeldende verdi av hale = Hale Så nå kan vi tydelig se rekkefølgen av variabel initialisering og konstruktørkall når et nytt objekt opprettes:
- Statiske variabler for basisklassen (
Animal
) initialiseres. I vårt tilfelle erAnimal
klassens variabel animalCount satt til 7700000. -
Statiske variabler for barneklassen (
Cat
) initialiseres.Merk: vi er fortsatt inne i konstruktøren
Animal
og vi har allerede vist:Animal base class constructor kjører
Har variablene til Animal-klassen allerede blitt initialisert?
Gjeldende verdi av statisk variabel animalCount = 7700000
Gjeldende verdi av hjernen i dyreklassen = Startverdien av hjernen i dyreklassen
Gjeldende verdi av hjertet i dyreklassen = Startverdien til hjertet i dyreklassen
Har variablene til katteklassen allerede blitt initialisert?
Gjeldende verdi av statisk variabel catCount = 37 -
Deretter initialiseres de ikke-statiske variablene til basisklassen . Vi tildelte dem spesifikt startverdier, som deretter erstattes i konstruktøren. Dyrekonstruktøren er ikke ferdig ennå, men startverdiene for hjerne og hjerte er allerede tildelt:
Animal base class constructor kjører
Har variablene til Animal-klassen allerede blitt initialisert?
Gjeldende verdi av statisk variabel animalCount = 7700000
Gjeldende verdi av hjerne i dyreklassen = Startverdi av hjerne i dyreklassen
Nåværende verdi av hjerte i dyreklassen = Startverdi på hjerte i dyreklassen -
Basisklassekonstruktøren starter.
Vi har allerede overbevist oss selv om at dette trinnet er fjerde: i de tre første trinnene i begynnelsen av konstruktørenAnimal
har mange variabler allerede blitt tildelt verdier. -
Ikke-statiske felt i barneklassen (
Cat
) initialiseres.
Dette skjer førCat
konstruktøren begynner å kjøre.
Når den begynner å kjøre, har halevariabelen allerede en verdi:Katteklassekonstruktøren har startet (Dyrekonstruktøren er allerede ferdig) Gjeldende verdi av statisk variabel catCount = 37 Gjeldende verdi av hale = Startverdi av hale i Cat-klassen
-
Konstruktøren av
Cat
barneklassen kallesOg det er slik det å lage et objekt ser ut i Java!
Jeg må si at vi ikke er store fans av utenat-læring, men det er best å huske rekkefølgen på variabel initialisering og konstruktørkall .
Dette vil i stor grad øke din forståelse av flyten av programmet, og tilstanden til objektene dine til enhver tid.
Dessuten bruker mange klasser ikke arv. I dette tilfellet gjelder ikke trinnene knyttet til basisklassen.
Mer lesing: |
---|
GO TO FULL VERSION