JavaRush /Java Blog /Random-IT /Costruttori di classi base

Costruttori di classi base

Pubblicato nel gruppo Random-IT
Ciao! L'ultima volta abbiamo parlato di costruttori e abbiamo imparato molto su di loro. Ora parleremo di cose come i costruttori di classi base. Cos'è una classe base ? Il fatto è che in Java diverse classi diverse possono avere un'origine comune. Costruttori della classe base - 2Questa si chiama eredità . Diverse classi discendenti possono avere una classe antenato comune. Ad esempio, immagina di avere una classe Animal(animale):

public class Animal {
  
   String name;
   int age;
}
Possiamo creare per questo, ad esempio, 2 classi discendenti - Cate Dog. Questo viene fatto utilizzando la parola chiave extends.

public class Cat extends Animal {

}

public class Dog extends Animal {
  
}
Questo potrebbe esserci utile in futuro. Ad esempio, se il compito è catturare i topi, creeremo un oggetto nel programma Cat. Se il compito è correre dietro a un bastone, utilizziamo l'oggetto Dog. E se creiamo un programma che simula una clinica veterinaria, funzionerà con la classe Animal(per poter curare sia cani che gatti). È molto importante ricordare per il futuro che quando si crea un oggetto, viene chiamato prima il costruttore della sua classe base e solo successivamente viene chiamato il costruttore della classe stessa, l'oggetto di cui stiamo creando. Cioè, quando si crea un oggetto, Catfunzionerà prima il costruttore della classe Animale solo dopo il costruttore Cat. Per essere sicuri di ciò, aggiungiamo i costruttori Cate Animalproduciamo l'output sulla console.

public class Animal {

   public Animal() {
       System.out.println("Animal constructor completed");
   }
}


public class Cat extends Animal {

   public Cat() {
       System.out.println("The constructor Cat worked!");
   }

   public static void main(String[] args) {
       Cat cat = new Cat();
   }
}
Uscita console:

Отработал конструктор Animal
Отработал конструктор Cat!
In effetti, è così che funziona! Cosa serve? Ad esempio, per evitare di duplicare i campi comuni di due classi. Ad esempio, ogni animale ha un cuore e un cervello, ma non tutti gli animali hanno una coda. Possiamo dichiarare campi comuni a tutti gli animali brainnella heartclasse genitore Animale un campo tailnella sottoclasse Cat. Ora creeremo un costruttore per la classe Cat, dove passeremo tutti e 3 i campi.

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");
   }
}
Fai attenzione:il costruttore funziona correttamente, sebbene la classe Catnon abbia campi braine heart. Questi campi sono stati “estratti” dalla classe base Animal. La classe discendente ha accesso ai campi della classe base, quindi Catsono visibili nella nostra classe. Pertanto, non abbiamo bisogno Catdi duplicare questi campi nella classe: possiamo prenderli dalla classe Animal. Inoltre, possiamo chiamare esplicitamente il costruttore della classe base nel costruttore della classe discendente. La classe base è anche chiamata “ superclasse ”, motivo per cui Java utilizza la parola chiave super. Nell'esempio precedente

public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }
Abbiamo assegnato separatamente ciascun campo presente nella nostra classe genitore. In effetti, non devi farlo. È sufficiente chiamare il costruttore della classe genitore e passargli i parametri necessari:

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");
   }
}
Nel costruttore, Catabbiamo chiamato il costruttore Animale gli abbiamo passato due campi. Dobbiamo solo inizializzare esplicitamente un campo, tailche Animalnon è presente. Ricordi come abbiamo detto che quando viene creato un oggetto, viene chiamato per primo il costruttore della classe genitore? Quindi, ecco perché la parola super()dovrebbe sempre venire prima nel costruttore! Altrimenti la logica dei costruttori verrà interrotta e il programma genererà un errore.

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");
   }
}
Il compilatore sa che quando si crea un oggetto di una classe discendente, viene chiamato per primo il costruttore della classe base. E se provi a modificare manualmente questo comportamento, non lo consentirà.

Il processo di creazione di un oggetto.

Sopra abbiamo visto un esempio con una classe base e genitore - Animale Cat. Ora, utilizzando queste due classi come esempio, esamineremo il processo di creazione di un oggetto e di inizializzazione delle variabili. Sappiamo che le variabili sono statiche e variabili di istanza (non statiche). Sappiamo anche che la classe base Animalha le proprie variabili e la classe discendente Catha le proprie. Aggiungiamo una variabile statica alla classe per Animalchiarezza . CatLa variabile animalCountdi classe Animalsarebbe il numero totale di specie animali sulla terra e la variabile catsCountsarebbe il numero di specie di gatti. Inoltre, assegneremo valori iniziali a tutte le variabili non statiche di entrambe le classi (che poi cambieranno nel costruttore).

public class Animal {

   String brain = "The initial value of brain in the Animal class";
   String heart = "The initial value of heart in the Animal class";

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println("The constructor of the Animal base class is being executed");
       System.out.println("Have the variables of the Animal class already been initialized?");
       System.out.println("The current value of the static variable animalCount = " + animalCount);
       System.out.println("Current value of brain in class Animal = " + this.brain);
       System.out.println("Current value of heart in class Animal = " + this.heart);
       System.out.println("Have the variables of the Cat class already been initialized?");
       System.out.println("The current value of the static variable catsCount = " + Cat.catsCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println("Animal base class constructor completed!");
       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 = "The initial value of tail in the Cat class";

   static int catsCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
       System.out.println("The current value of the static variable catsCount = " + catsCount);
       System.out.println("Current value tail = " + this.tail);
       this.tail = tail;
       System.out.println("Current value tail = " + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Brain", "Heart", "Tail");
   }
}
Quindi, creiamo un nuovo oggetto della classe Catereditata da Animal. Aggiungiamo l'output dettagliato della console al nostro programma per vedere cosa accadrà e in quale ordine. Questo è ciò che verrà visualizzato sulla console come risultato della creazione di un oggetto Cat:

Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее meaning статической переменной animalCount = 7700000
Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее meaning статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее meaning brain = Мозг
Текущее meaning heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее meaning статической переменной catsCount = 37
Текущее meaning tail = Изначальное meaning tail в классе Cat
Текущее meaning tail = Хвост
Quindi, ora possiamo vedere chiaramente in quale ordine le variabili vengono inizializzate e i costruttori vengono chiamati quando si crea un nuovo oggetto:
  1. Le variabili statiche della classe base ( ) vengono inizializzate Animal. Nel nostro caso alla variabile animalCountclass Animalviene assegnato il valore 7700000.

  2. Le variabili statiche della classe discendente ( ) vengono inizializzate Cat. Fai attenzione: siamo ancora all'interno del costruttore Animale la console dice già:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее meaning статической переменной catsCount = 37
  3. Successivamente, vengono inizializzate le variabili non statiche della classe base . Abbiamo assegnato loro specificatamente i valori iniziali, che vengono poi modificati in nuovi nel costruttore. Il costruttore Animalnon ha ancora terminato il suo lavoro, ma brainsono heartgià stati assegnati i valori iniziali:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
  4. Il costruttore della classe base inizia a funzionare .

    Abbiamo già visto che questa fase è solo la quarta di seguito: nei primi tre punti, nel momento in cui il costruttore inizia a lavorare, Animala molte variabili sono già stati assegnati dei valori.

  5. Inizializzazione dei campi non statici di una classe figlia ( Cat).

    Succede prima che il designer Catinizi a lavorare.

    Nel momento in cui ha iniziato a lavorare, la variabile tailaveva già un valore:

    
    Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
    Текущее meaning статической переменной catsCount = 37
    Текущее meaning tail = Изначальное meaning tail в классе Cat
  6. Viene chiamato il costruttore della classe discendente Cat

Ecco come appare il processo di creazione di un oggetto in Java! Devo dire che non siamo grandi fan del cramming, ma è meglio memorizzare l'ordine di inizializzazione delle variabili e di chiamata dei costruttori e ricordarli per il futuro . Ciò aumenterà notevolmente la tua comprensione dell'avanzamento del programma e dello stato dei tuoi oggetti in un dato momento. Inoltre, le classi spesso non hanno classi genitore dirette (superclassi/classi base). In questo caso gli elementi associati alla classe base non verranno eseguiti.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION