CodeGym /Blog Java /Aleatoriu /Constructorii clasei de bază
John Squirrels
Nivel
San Francisco

Constructorii clasei de bază

Publicat în grup
Bună! Ultima dată am vorbit despre constructori și am învățat multe despre ei. Acum vom vorbi despre constructorii clasei de bază .
Constructorii clasei de bază - 1
Ce este o clasă de bază ? Are de-a face cu faptul că în Java mai multe clase diferite pot avea o origine comună.
Constructorii clasei de bază - 2
Aceasta se numește moștenire . Mai multe clase de copii pot avea un strămoș comun. De exemplu, imaginați-vă că avem o Animalclasă:

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 Catobiect, constructorul Animaleste rulat mai întâi și numai după aceeaCatconstructor 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 Animalclasa părinte, și un câmp de coadă în Catsubclasă. . Acum vom declara un Catconstructor 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 Catnu are câmpuri pentru creier și inimă . Aceste câmpuri sunt „moștenite” din Animalclasa de bază. Clasa care moștenește are acces la câmpurile clasei de bază , deci sunt vizibile în Catclasa noastră. Ca rezultat, nu trebuie să duplicăm aceste câmpuri în Catclasă. Le putem lua de la Animalclasă. 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 Catconstructor, am apelat Animalconstructorul ș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ă Animalclasa de bază are variabile, iar Catclasa copil are propriile sale. Pentru claritate, vom adăuga câte o variabilă statică la clasele Animalși Cat. Variabila animalCount din Animalclasă 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 Catclasei, 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 Catobiect 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:
  1. Variabilele statice ale clasei de bază ( Animal) sunt inițializate. În cazul nostru, Animalvariabila animalCount a clasei este setată la 7700000.

  2. Variabilele statice ale clasei copil ( Cat) sunt inițializate.

    Notă: suntem încă în interiorul Animalconstructorului ș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


  3. 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


  4. Pornește constructorul clasei de bază .
    Ne-am convins deja că acest pas este al patrulea: în primii trei pași de la începutul constructorului Animal, multor variabile li s-au atribuit deja valori.


  5. Câmpurile nestatice ale clasei copil ( Cat) sunt inițializate.
    Acest lucru se întâmplă înainte ca Catconstructorul 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


  6. Constructorul Catclasei 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ă.

Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION