CodeGym /Java Blog /Willekeurig /Constructeurs van basisklassen
John Squirrels
Niveau 41
San Francisco

Constructeurs van basisklassen

Gepubliceerd in de groep Willekeurig
Hoi! De vorige keer hadden we het over constructeurs en we hebben er veel over geleerd. Nu gaan we het hebben over constructors van basisklassen .
Constructeurs van basisklassen - 1
Wat is een basisklasse ? Het heeft te maken met het feit dat in Java verschillende klassen een gemeenschappelijke oorsprong kunnen hebben.
Constructeurs van basisklassen - 2
Dit wordt erfenis genoemd . Verschillende kindklassen kunnen één gemeenschappelijke voorouder hebben. Stel je bijvoorbeeld voor dat we een Animalklasse hebben:

public class Animal {
  
   String name;
   int age;
}
We kunnen 2 kinderklassen declareren: Caten 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 Catobject wordt eerst deAnimal constructor uitgevoerd en pas daarna deCatconstructeur uitgevoerd . Om dit te zien, voegt u wat console-uitvoer toe aan de Catand- Animalconstructors.

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 Animalouderklasse, en een staartveld in de Catsubklasse. . Nu declareren we een Catklassenconstructor 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 Catklasse geen hersen- en hartvelden . Deze velden zijn "geërfd" van de Animalbasisklasse. De overervende klasse heeft toegang tot de velden van de basisklasse , zodat ze zichtbaar zijn in onze Catklasse. Als gevolg hiervan hoeven we deze velden niet in de Catklas 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 Catconstructor hebben we de Animalconstructor 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: Animalen 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 Animalbasisklasse variabelen heeft en de Catonderliggende klasse zijn eigen. Voor de duidelijkheid voegen we elk één statische variabele toe aan de klassen Animaland 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 Catklasse, 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 Catobject 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:
  1. Statische variabelen van de basisklasse ( Animal) worden geïnitialiseerd. In ons geval is de variabele animalCountAnimal van de klasse ingesteld op 7700000.

  2. Statische variabelen van de onderliggende klasse ( Cat) worden geïnitialiseerd.

    Opmerking: we zitten nog steeds in de Animalconstructor 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


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


  4. 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 de Animalconstructor hebben al veel variabelen waarden gekregen.


  5. Niet-statische velden van de onderliggende klasse ( Cat) worden geïnitialiseerd.
    Dit gebeurt voordat de Catconstructor 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


  6. De constructor van de Catonderliggende klasse wordt aangeroepen

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

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