

Animal
clasă:
public class Animal {
String name;
int age;
}
Putem declara 2 clase de copii: Cat
și Dog
. Acest lucru se face folosind cuvântul cheie extins .
public class Cat extends Animal {
}
public class Dog extends Animal {
}
S-ar putea să găsim acest lucru util în viitor. De exemplu, dacă există o sarcină pentru a prinde șoareci, vom crea un Cat
obiect în programul nostru. Dacă sarcina este să urmărim un băț, atunci vom folosi un Dog
obiect. Și dacă creăm un program care simulează o clinică veterinară, acesta va funcționa cu Animal
clasa (și astfel va putea trata atât pisicile, cât și câinii). Este foarte important să ne amintim că atunci când un obiect este creat, constructorul clasei sale de bază este mai întâi numit . Numai după ce acel constructor este terminat, programul execută constructorul clasei corespunzătoare obiectului pe care îl creăm. Cu alte cuvinte, atunci când se creează un Cat
obiect, constructorul Animal
este rulat mai întâi și numai după aceeaCat
constructor executat . Pentru a vedea acest lucru, adăugați o ieșire de consolă la constructori Cat
și 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();
}
}
Ieșire consolă: Constructor animal executat Constructor Cat executat! Într-adevăr, funcționează așa! De ce? Un motiv este de a evita duplicarea câmpurilor partajate între cele două clase. De exemplu, fiecare animal are o inimă și creier, dar nu orice animal are o coadă. Am putea declara câmpuri ale creierului și inimii , care sunt comune tuturor animalelor, în Animal
clasa părinte, și un câmp de coadă în Cat
subclasă. . Acum vom declara un Cat
constructor de clasă care preia argumente pentru toate cele 3 câmpuri.
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");
}
}
Notă: Constructorul funcționează corect, chiar dacă clasa Cat
nu are câmpuri pentru creier și inimă . Aceste câmpuri sunt „moștenite” din Animal
clasa de bază. Clasa care moștenește are acces la câmpurile clasei de bază , deci sunt vizibile în Cat
clasa noastră. Ca rezultat, nu trebuie să duplicăm aceste câmpuri în Cat
clasă. Le putem lua de la Animal
clasă. Mai mult, putem apela explicit constructorul clasei de bază în constructorul clasei copil. O clasă de bază este numită și „ superclasă ”. De aceea, Java folosește cuvântul cheie super pentru a indica clasa de bază. În exemplul anterior
public Cat(String brain, String heart, String tail) {
this.brain = brain;
this.heart = heart;
this.tail = tail;
}
Am atribuit separat fiecare câmp din clasa noastră părinte. De fapt, nu trebuie să facem asta. Este suficient să apelați constructorul clasei părinte și să transmiteți argumentele necesare:
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");
}
}
În Cat
constructor, am apelat Animal
constructorul și am trecut două câmpuri. Aveam un singur câmp de inițializat în mod explicit: tail , care nu este în Animal
. Amintiți-vă că am menționat că constructorul clasei părinte este apelat mai întâi atunci când este creat un obiect? De aceea super() ar trebui să fie întotdeauna primul într-un constructor! În caz contrar, logica constructorului va fi încălcată și programul va genera o eroare.
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");
}
}
Compilatorul știe că atunci când un obiect al unei clase copil este creat, constructorul clasei de bază este apelat primul. Și dacă încercați să modificați manual acest comportament, compilatorul nu vă va permite.
Cum este creat un obiect
Am analizat anterior un exemplu cu o clasă de bază și o clasă părinte:Animal
și Cat
. Folosind aceste două clase ca exemple, ne vom uita acum la procesul de creare a unui obiect și de inițializare a variabilelor. Știm că există variabile statice și de instanță (non-statice) . De asemenea, știm că Animal
clasa de bază are variabile, iar Cat
clasa copil are propriile sale. Pentru claritate, vom adăuga câte o variabilă statică la clasele Animal
și Cat
. Variabila animalCount din Animal
clasă va reprezenta numărul total de specii de animale de pe Pământ și catCountvariabila va semnifica numărul de specii de pisici. În plus, vom atribui valori de pornire tuturor variabilelor non-statice din ambele clase (care vor fi apoi modificate în 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");
}
}
Deci, creăm o nouă instanță a Cat
clasei, care moștenește Animal
. Am adăugat câteva rezultate detaliate ale consolei pentru a vedea ce se întâmplă și în ce ordine. Iată ce va fi afișat atunci când un Cat
obiect este creat: Constructorul clasei de bază Animal rulează Au fost deja inițializate variabilele clasei Animal? Valoarea curentă a variabilei statice animalCount = 7700000 Valoarea curentă a creierului în clasa Animal = Valoarea inițială a creierului în clasa Animal Valoarea curentă a inimii în clasa Animal = Valoarea inițială a inimii în clasa Animal Au variabilele clasei Animal deja a fost initializat? Valoarea curentă a variabilei statice catCount = 37 Constructorul clasei de bază pentru animale este finalizat! Valoarea curentă a creierului = creier Valoarea curentă inimă = inimă Constructorul clasei pisici a început (constructorul animal este deja terminat) Valoarea curentă a variabilei statice catCount = 37 Valoarea curentă a cozii = valoarea inițială a cozii în clasa pisicii Valoarea curentă a cozii = Coadă Deci, acum putem vedea clar ordinea inițializării variabilelor și a apelurilor de constructor atunci când este creat un nou obiect:
- Variabilele statice ale clasei de bază (
Animal
) sunt inițializate. În cazul nostru,Animal
variabila animalCount a clasei este setată la 7700000. -
Variabilele statice ale clasei copil (
Cat
) sunt inițializate.Notă: suntem încă în interiorul
Animal
constructorului și am afișat deja:Constructorul clasei de bază Animal rulează
Au fost deja inițializate variabilele clasei Animal?
Valoarea curentă a variabilei statice animalCount = 7700000
Valoarea curentă a creierului în clasa Animal = Valoarea inițială a creierului în clasa Animal
Valoarea curentă a inimii în clasa Animal = Valoarea inițială a inimii în clasa Animal
Au variabilele clasei Animal deja a fost initializat?
Valoarea curentă a variabilei statice catCount = 37 -
Apoi variabilele non-statice ale clasei de bază sunt inițializate. Le-am atribuit în mod special valori inițiale, care sunt apoi înlocuite în constructor. Constructorul Animal nu s-a terminat încă, dar valorile inițiale ale creierului și inimii au fost deja atribuite:
Constructorul clasei de bază Animal rulează
Au fost deja inițializate variabilele clasei Animal?
Valoarea curentă a variabilei statice animalCount = 7700000
Valoarea curentă a creierului în clasa Animal = Valoarea inițială a creierului în clasa Animal
Valoarea curentă a inimii în clasa Animal = Valoarea inițială a inimii în clasa Animal -
Pornește constructorul clasei de bază .
Ne-am convins deja că acest pas este al patrulea: în primii trei pași de la începutul constructoruluiAnimal
, multor variabile li s-au atribuit deja valori. -
Câmpurile nestatice ale clasei copil (
Cat
) sunt inițializate.
Acest lucru se întâmplă înainte caCat
constructorul să înceapă să ruleze.
Când începe să ruleze, variabila coadă are deja o valoare:Constructorul clasei pisici a început (Constructorul Animal este deja terminat) Valoarea curentă a variabilei statice catCount = 37 Valoarea curentă a cozii = Valoarea inițială a cozii în clasa Cat
-
Constructorul
Cat
clasei copil este numitȘi așa arată crearea unui obiect în Java!
Trebuie să spun că nu suntem mari fani ai învățării prin memorare, dar cel mai bine este să memorăm ordinea inițializării variabilelor și apelurile constructorului .
Acest lucru vă va crește considerabil înțelegerea fluxului programului și a stării obiectelor dvs. în orice moment anume.
În plus, multe clase nu folosesc moștenirea. În acest caz, pașii legați de clasa de bază nu se aplică.
Mai multe lecturi: |
---|
GO TO FULL VERSION