JavaRush /Java Blog /Random EN /Base class constructors

Base class constructors

Published in the Random EN group
Hello! Last time we talked about constructors , and we learned a lot about them. Now we will talk about such a thing as base class constructors. What is a base class ? The fact is that in Java, several different classes can have a common origin. Base class constructors - 2This is called inheritance . Several descendant classes can have one common ancestor class. For example, imagine that we have a class Animal(animal):
public class Animal {

   String name;
   int age;
}
We can create for it, for example, 2 descendant classes - Catand Dog. This is done using the keyword extends.
public class Cat extends Animal {

}

public class Dog extends Animal {

}
This may be useful to us in the future. For example, if the task is to catch mice, we will create an object in the program Cat. If the task is to run after a stick, then we use the object Dog. And if we create a program that simulates a veterinary clinic, it will work with the class Animal(to be able to treat both cats and dogs). It is very important to remember for the future that when creating an object, the constructor of its base class is called first , and only then the constructor of the class itself, the object of which we are creating, is called. That is, when creating an object, Catthe class constructor will work first Animal, and only then the constructor Cat. To make sure of this, let’s add to the constructors Catand Animaloutput to the 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();
   }
}
Console output:

Отработал конструктор Animal
Отработал конструктор Cat!
Indeed, this is how it all works! What is it for? For example, to avoid duplicating common fields of two classes. For example, every animal has a heart and a brain, but not every animal has a tail. We can declare fields common to all animals brainin heartthe parent class Animal, and a field tailin the subclass Cat. Now we will create a constructor for the class Cat, where we will pass all 3 fields.
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");
   }
}
Pay attention:the constructor works successfully, although the class Catdoes not have fields brainand heart. These fields were “pulled up” from the base class Animal. The descendant class has access to the fields of the base class, so Catthey are visible in our class. Therefore, we do not need Catto duplicate these fields in the class - we can take them from the class Animal. Moreover, we can explicitly call the constructor of the base class in the constructor of the descendant class. The base class is also called the “ superclass ,” which is why Java uses the keyword super. In the previous example
public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }
We separately assigned each field that is in our parent class. In fact, you don't have to do this. It is enough to call the constructor of the parent class and pass it the necessary parameters:
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 the constructor, Catwe called the constructor Animaland passed two fields to it. We only have to explicitly initialize one field - tailwhich is Animalnot present. Remember how we said that when an object is created, the constructor of the parent class is called first? So, this is why the word super()should always come first in the constructor! Otherwise, the logic of the constructors will be broken and the program will generate an error.
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");
   }
}
The compiler knows that when creating an object of a descendant class, the constructor of the base class is called first. And if you try to manually change this behavior, it will not allow it.

The process of creating an object.

Above we looked at an example with a base and parent class - Animaland Cat. Now, using these two classes as an example, we will look at the process of creating an object and initializing variables. We know that variables are static and instance variables (non-static). We also know that the base class Animalhas its own variables, and the descendant class Cathas its own. Let's add one static variable to the class for Animalclarity . The class Catvariable would be the total number of animal species on earth, and the variable would be the number of cat species. In addition, we will assign starting values ​​to all non-static variables of both classes (which will then change in the constructor). animalCountAnimalcatsCount
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");
   }
}
So, we create a new object of the class Catinherited from Animal. Let's add detailed console output to our program to see what will happen and in what order. This is what will be output to the console as a result of creating an object 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 = Хвост
So, now we can clearly see in what order variables are initialized and constructors are called when creating a new object:
  1. Static variables of the base class ( ) are initialized Animal. In our case, the animalCountclass variable Animalis assigned the value 7700000.

  2. The static variables of the descendant class ( ) are initialized Cat. Pay attention - we are still inside the constructor Animal, and the console already says:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее meaning статической переменной catsCount = 37
  3. Next, non-static variables of the base class are initialized . We specifically assigned them initial values, which are then changed to new ones in the constructor. The constructor Animalhas not yet completed its work, but the initial values brain​​have heartalready been assigned:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее meaning статической переменной animalCount = 7700000
        Текущее meaning brain в классе Animal = Изначальное meaning brain в классе Animal
        Текущее meaning heart в классе Animal = Изначальное meaning heart в классе Animal
  4. The base class constructor starts working .

    We have already seen that this stage is only the fourth: in the first three points, at the time the constructor starts working, Animalmany variables have already been assigned values.

  5. Initializing non-static fields of a child class ( Cat).

    It happens before the designer Catstarts working.

    At the time he started working, the variable tailalready had a value:

    
    Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
    Текущее meaning статической переменной catsCount = 37
    Текущее meaning tail = Изначальное meaning tail в классе Cat
  6. The constructor of the descendant class is called Cat

This is what the process of creating an object looks like in Java! I must say that we are not big fans of cramming, but it is better to memorize the order of initializing variables and calling constructors and remembering them for the future . This will greatly increase your understanding of the progress of the program and the state of your objects at any given moment. Moreover, classes often do not have direct parent classes (superclasses/base classes). In this case, the items associated with the base class will not be executed.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION