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:
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.
// 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 }
// Classe com construtor default implícito - por não possuir outros construtores
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.
// 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 }
// Classe com construtor sem chamar o construtor com parâmetro Endereco da classe Pai
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:
// 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 }
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).
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:
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.