Olá Pessoal, tudo bom?
Hoje vamos falar sobre um erro “Implicit super constructor Classe() is undefined. Must explicitly invoke another constructor” que ocorre nas classes ou construtores, quando temos uma herança entre classes com associações obrigatórias. Não entendeu muito veja a parte sobre associações obrigatórias desse artigo. Veja a descrição do erro e sua solução na continuação…
Descrição do Erro
Suponha uma hierarquia da classe Pessoa como mostra a Figura 01:
Como a Figura 01 indica a classe Pessoa obrigatoriamente deve possuir um Endereco. Qual é a melhor maneira de obrigar uma classe a passar determinada informação? Inserindo esta informação no construtor da classe base e removendo o construtor sem parâmetros, ou deixando de gerá-lo automaticamente por agora possuir um construtor. Dessa forma vamos adicionar um parâmetro Endereco ao construtor da classe Pessoa, como mostra o código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public abstract class Pessoa { private long id; private String nome; private String email; private String telefone; private Date dataNascimento; private String usuario; private String senha; //Devido a associacao entre Pessoa e Endereco private Endereco endereco; public Pessoa(Endereco endereco){ this.endereco = endereco; } //Metodos getters e setters } |
Agora se você implementar diretamente a classe Passageiro um dos dois código abaixo, irá gerar o erro Implicit super constructor Classe() is undefined. Must explicitly invoke another constructor.
1 2 3 4 5 6 7 8 |
// Classe com construtor default implícito - por não possuir outros construtores public class Passageiro extends Pessoa { private String documento; private String numeroCartao; //Metodos getters e setters } |
O código acima gera o erro, pois a classe Passageiro possui um construtor sem argumentos como default, ou seja, criado automaticamente pelo Java. Como o construtor sem argumentos default, chama o construtor sem argumentos da classe pai, o qual não existe, o irá aparecer.
1 2 3 4 5 6 7 8 9 10 11 |
// Classe com construtor sem chamar o construtor com parâmetro Endereco da classe Pai public class Passageiro extends Pessoa { private String documento; private String numeroCartao; public Passageiro(){ } //Metodos getters e setters } |
O código acima gera o erro apesar de a classe Passageiro possuir um construtor. Pois esse continua chamando um construtor sem argumentos da classe pai. A primeira linha de qualquer construtor, senão houver a chamada super(), o Java irá implicitamente por. Assim no caso do segundo código na primeira linha do construtor, entre as linhas 7 e 8, existe uma chamada super(), a qual representa uma chamada ao construtor sem argumentos.
Por fim o código abaixo ainda gera o erro, pois agora a chamada ao construtor da classe Pai está explícita:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Classe com construtor sem chamar o construtor com parâmetro Endereco da classe Pai public class Passageiro extends Pessoa { private String documento; private String numeroCartao; public Passageiro(){ super(); } //Metodos getters e setters } |
Solução
Para resolver esse problema devemos aplicar 2 passos.
O primeiro está dentro do construtor default (se este não existir deverá ser criado). O qual deverá ser adicionado na primeira linha do construtor, uma chamada ao construtor da classe pai, Pessoa, invocando o construtor corretamente ao passar o argumento endereco, super(endereco).
1 2 3 4 5 6 7 8 9 10 11 |
public class Passageiro extends Pessoa { private String documento; private String numeroCartao; public Passageiro(){ super(endereco); } //Metodos getters e setters } |
Mas isso causa um erro, pois não existe a variável endereco, assim o segundo passo vem desse erro, estabelecendo uma pergunta, “Onde está sendo recebida essa instância de endereco?“. Nesse momento nenhum lugar recebe essa instância. Assim, para corrigir esse erro e continuar a existir a obrigação de Endereço para a hierarquia de Pessoa, é necessário adicionar um parâmetro Endereco ao construtor de Passageiro também, o qual ficará com o seguinte código:
1 2 3 4 5 6 7 8 9 10 11 |
public class Passageiro extends Pessoa { private String documento; private String numeroCartao; public Passageiro(Endereco endereco){ super(endereco); } //Metodos getters e setters } |
Agora analisando o diagrama UML da Figura 01:
Faz sentido uma instância de Passageiro ou Funcionario, receber uma instância de Endereco?
Sim, todas as associações de uma classe Pai são transitivas as classes Filhas, ou seja, se Pessoa possui um Endereco, logo Passageiro e Funcionario, também devem possuir Endereço, assim está correto que as classes filhas possuam um construtor que receba Endereco.
finnaly{
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Leave a Reply