Oi Samuel, tudo bem?
Esse é um erro bem comum para desenvolvedores, mas que pode ser facilmente evitado assim que entendemos como o construtor se comporta com a herança. Praticamente qualquer dúvida, independente da tecnologia relacionada, tem suas respostas na documentação. Com Java não é diferente, vendo a documentação da palavra-chave super
:
"Se um construtor não invoca explicitamente um construtor de superclasse, o compilador Java insere automaticamente uma chamada para o construtor sem argumento da superclasse. Se a superclasse não tiver um construtor sem argumentos, você receberá um erro em tempo de compilação."
Ok, mas o que isso quer dizer?
Como será explicado na aula 4 do curso, ao criarmos a classe Gerente
que herda da classe Funcionario
, o compilador insere automaticamente um construtor invisível que invoca o construtor da classe mãe através da palavra-chave super()
, ou seja, por baixo dos panos é isso que acontece:
public class Gerente extends Funcionario {
public Gerente() {
super(); //chamando construtor de Funcionario
}
}
Portanto, se olharmos para o seu primeiro código, é isso que vemos:
Gerente(String nome, String cpf, double salario, int senha) {
super.setCpf(cpf);
super.setNome(nome);
super.setSalario(salario);
this.senha = senha;
}
Porém, na realidade, é isso que acontece:
Gerente(String nome, String cpf, double salario, int senha) {
super();
super.setCpf(cpf);
super.setNome(nome);
super.setSalario(salario);
this.senha = senha;
}
Existe uma chamada implícita ao construtor padrão (sem argumentos) da classe Funcionario
, o problema é que o construtor padrão sem argumentos da classe Funcionario
deixou de existir (ou melhor, foi substituído) a partir do momento em que você criou esse outro construtor:
Funcionario(String nome, String cpf, double salario){
this.nome = nome;
this.cpf = cpf;
this.salario = salario;
}
E como vimos na documentação:
"Se a superclasse não tiver um construtor sem argumentos, você receberá um erro em tempo de compilação."
Como resolver isso? Simples, temos duas maneiras:
1. Criar um construtor vazio na classe Funcionario
para que o seu primeiro código não dê nenhum erro ao tentar chamar o construtor padrão sem argumentos da classe mãe:
public class Funcionario {
//Código omitido
//Construtor sem argumentos que receberá a chamada de super()
public Funcionario() {
}
public Funcionario(String nome, String cpf, double salario) {
this.nome = nome;
this.cpf = cpf;
this.salario = salario;
}
Fazendo isso, quando o construtor de Gerente
usar o super()
por baixo dos panos, esse código irá rodar:
Gerente(String nome, String cpf, double salario, int senha) {
super.setCpf(cpf);
super.setNome(nome);
super.setSalario(salario);
this.senha = senha;
}
2. Adicionar uma chamada explícita ao construtor com argumentos da classe mãe (o que você fez):
public class Gerente extends Funcionario{
//Código omitido
public Gerente(String nome, String cpf, double salario) {
super(nome, cpf, salario);
}
Aqui, ao passarmos parâmetros dentro de super(nome, cpf, salario)
, estamos declarando explicitamente que não queremos o construtor padrão da classe Funcionario
, mas sim o construtor que recebe esses exatos parâmetros!
Lembrando:
"Se um construtor não invoca explicitamente um construtor de superclasse, o compilador Java insere automaticamente uma chamada para o construtor sem argumento da superclasse."
Bom, aqui estamos invocando explicitamente o construtor da superclasse através do super(nome, cpf, salario)
.
Espero ter ajudado, qualquer dúvida é só avisar!
Bons estudos!!