CodeGym /Blogue Java /Random-PT /Construtores de classe base
John Squirrels
Nível 41
San Francisco

Construtores de classe base

Publicado no grupo Random-PT
Oi! Da última vez falamos sobre construtores e aprendemos muito sobre eles. Agora vamos falar sobre construtores de classe base .
Construtores de classe base - 1
O que é uma classe base ? Tem a ver com o fato de que em Java várias classes diferentes podem ter uma origem comum.
Construtores de classe base - 2
Isso se chama herança . Várias classes filhas podem ter um ancestral comum. Por exemplo, imagine que temos uma Animalclasse:

public class Animal {
  
   String name;
   int age;
}
Podemos declarar 2 classes filhas: Cate Dog. Isso é feito usando a palavra-chave extends .

public class Cat extends Animal {

}

public class Dog extends Animal {
  
}
Podemos achar isso útil no futuro. Por exemplo, se houver uma tarefa para pegar ratos, criaremos um Cat objeto em nosso programa. Se a tarefa for correr atrás de um pedaço de pau, usaremos um Dog objeto. E se criarmos um programa que simule uma clínica veterinária, ele funcionará com a Animal turma (e assim poderá atender tanto cães quanto gatos). É muito importante lembrar que quando um objeto é criado, primeiro é chamado o construtor de sua classe base . Somente após o término desse construtor é que o programa executa o construtor da classe correspondente ao objeto que estamos criando. Em outras palavras, ao criar um Catobjeto, o Animalconstrutor é executado primeiro e só depois é executado oCatconstrutor executado . Para ver isso, adicione alguma saída do console aos construtores Cate 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();
   }
}
Saída do console: Construtor animal executado Construtor gato executado! De fato, funciona assim! Por que? Um motivo é evitar a duplicação de campos compartilhados entre as duas classes. Por exemplo, todo animal tem coração e cérebro, mas nem todo animal tem rabo. Poderíamos declarar os campos do cérebro e do coração , que são comuns a todos os animais, na Animalclasse pai, e um campo de cauda na Catsubclasse. . Agora vamos declarar um Catconstrutor de classe que recebe argumentos para todos os 3 campos.

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");
   }
}
Observação: o construtor funciona corretamente mesmo que a Catclasse não tenha campos cerebrais e cardíacos . Esses campos são "herdados" da Animalclasse base. A classe herdeira tem acesso aos campos da classe base , portanto, eles ficam visíveis em nossa Catclasse. Como resultado, não precisamos duplicar esses campos na Catclasse. Podemos retirá-los da Animalclasse. Além disso, podemos chamar explicitamente o construtor da classe base no construtor da classe filha. Uma classe base também é chamada de " superclasse ". É por isso que Java usa a palavra-chave super para indicar a classe base. No exemplo anterior

public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }
Atribuímos separadamente cada campo em nossa classe pai. Na verdade, não precisamos fazer isso. Basta chamar o construtor da classe pai e passar os argumentos necessários:

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");
   }
}
No Catconstrutor, chamamos o Animalconstrutor e passamos dois campos. Tínhamos apenas um campo para inicializar explicitamente: tail , que não está em Animal. Lembra que mencionamos que o construtor da classe pai é chamado primeiro quando um objeto é criado? É por isso que super() deve sempre ser o primeiro em um construtor! Caso contrário, a lógica do construtor será violada e o programa gerará um erro.

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");
   }
}
O compilador sabe que quando um objeto de uma classe filha é criado, o construtor da classe base é chamado primeiro. E se você tentar alterar manualmente esse comportamento, o compilador não permitirá.

Como um objeto é criado

Anteriormente, vimos um exemplo com uma classe base e pai: Animale Cat. Usando essas duas classes como exemplos, veremos agora o processo de criação de um objeto e inicialização de variáveis. Sabemos que existem variáveis ​​estáticas e de instância (não estáticas) . Também sabemos que a Animalclasse base possui variáveis ​​e a Catclasse filha possui suas próprias. Para maior clareza, adicionaremos uma variável estática a cada uma das classes Animale Cat. A variável animalCount na Animalclasse representará o número total de espécies animais na Terra, e a variável catCountvariável significará o número de espécies de gatos. Além disso, atribuiremos valores iniciais a todas as variáveis ​​não estáticas em ambas as classes (que serão alteradas no construtor).

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");
   }
}
Portanto, estamos criando uma nova instância da Catclasse, que herda Animal. Adicionamos algumas saídas de console detalhadas para ver o que está acontecendo e em que ordem. Isso é o que será exibido quando um Catobjeto for criado: O construtor da classe base Animal está em execução As variáveis ​​da classe Animal já foram inicializadas? Valor atual da variável estática animalCount = 7700000 Valor atual do cérebro na classe Animal = Valor inicial do cérebro na classe Animal Valor atual do coração na classe Animal = Valor inicial do coração na classe Animal Já tem as variáveis ​​da classe Gato foi inicializado? Valor atual da variável estática catCount = 37 O construtor da classe base Animal está pronto! Valor atual de brain = Brain Valor atual heart = Heart O construtor da classe cat foi iniciado (o construtor Animal já terminou) Valor atual da variável estática catCount = 37 Valor atual de tail = Valor inicial de tail na classe Cat Valor atual de tail = Cauda Então, agora podemos ver claramente a ordem de inicialização de variáveis ​​e chamadas de construtor quando um novo objeto é criado:
  1. As variáveis ​​estáticas da classe base ( Animal) são inicializadas. Em nosso caso, a variável animalCountAnimal da classe é definida como 7700000.

  2. As variáveis ​​estáticas da classe filha ( Cat) são inicializadas.

    Obs: ainda estamos dentro do Animalconstrutor e já exibimos:

    O construtor da classe base Animal está em execução
    As variáveis ​​da classe Animal já foram inicializadas?
    Valor atual da variável estática animalCount = 7700000
    Valor atual do cérebro na classe Animal = Valor inicial do cérebro na classe Animal
    Valor atual do coração na classe Animal = Valor inicial do coração na classe Animal
    Já tem as variáveis ​​da classe Gato foi inicializado?
    Valor atual da variável estática catCount = 37


  3. Em seguida, as variáveis ​​não estáticas da classe base são inicializadas. Atribuímos especificamente valores iniciais a eles, que são então substituídos no construtor. O construtor Animal ainda não terminou, mas os valores iniciais de brain e heart já foram atribuídos:

    O construtor da classe base Animal está em execução
    As variáveis ​​da classe Animal já foram inicializadas?
    Valor atual da variável estática animalCount = 7700000
    Valor atual do cérebro na classe Animal = Valor inicial do cérebro na classe Animal
    Valor atual do coração na classe Animal = Valor inicial do coração na classe Animal


  4. O construtor da classe base é iniciado.
    Já nos convencemos de que esta etapa é a quarta: nas três primeiras etapas do início do Animalconstrutor, muitas variáveis ​​já receberam valores.


  5. Os campos não estáticos da classe filha ( Cat) são inicializados.
    Isso acontece antes que o Catconstrutor comece a executar.
    Quando começa a rodar, a variável tail já tem um valor:

    O construtor da classe cat foi iniciado (o construtor Animal já terminou) Valor atual da variável estática catCount = 37 Valor atual de tail = Valor inicial de tail na classe Cat


  6. O construtor da Catclasse filha é chamado

    E é assim que a criação de um objeto se parece em Java!

    Devo dizer que não somos grandes fãs de aprendizado mecânico, mas é melhor memorizar a ordem de inicialização de variáveis ​​e chamadas de construtor .

    Isso aumentará muito sua compreensão do fluxo do programa e do estado de seus objetos em qualquer momento específico.

    Além disso, muitas classes não usam herança. Nesse caso, as etapas relacionadas à classe base não se aplicam.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION