public class Conta { public double Saldo { get; set; }
public double CalcularTaxaAdministrativa()
{
return 1;
}
}
public class ContaCorrente : Conta { public double CalcularTaxaAdministrativa() { return 0; } }
public class Conta { public double Saldo { get; set; }
public double CalcularTaxaAdministrativa()
{
return 1;
}
}
public class ContaCorrente : Conta { public double CalcularTaxaAdministrativa() { return 0; } }
Oi Bruno, não sou especialista, mas a explicação das alternativas ajudaram bastante. A mae precisa marcar o método como virtual e a filha precisa usar o override para indicar a sobreescrita. Dessa forma obrigada a pessoa a pensar sobre herança no momento do design da classe... Acho uma boa prática, na verdade.
Oi Alberto, entendi o que você disse, porém a minha dúvida é justamente nisso. Na classe "pai" não está como Virtual, como voce pode ver no código que colei e na filha não existe a sobrescrita. Tendo isso em mente, porque nesse código
public class Conta { public double Saldo { get; set; }
public double CalcularTaxaAdministrativa()
{
return 1;
}
} public class ContaCorrente : Conta { public double CalcularTaxaAdministrativa() { return 0; } }
Ao fazer na Main: ContaCorrente c = new ContaCorrente (); c.CalcularTaxaAdministrativa(); <<
Ele retornaria 0 ao invés de um ? A explicação não ficou clara para mim. Achei que por não haver uma sobrescrita, ele executaria o método da classe pai.
Olá, Bruno. Tudo bom?
Vamos começar pelo código da Conta
:
public class Conta
{
public double Saldo { get; set; }
public double CalcularTaxaAdministrativa()
{
return 1;
}
}
Aqui dizemos ao compilador "A Classe Conta
possui uma propriedade Saldo
e um método não-virtual CalcularTaxaAdministrativa
".
Quando temos uma referência de Conta
, a aplicação não tem dúvidas, já sabe exatamente qual método executar, é este que retorna 1
.
Agora, a ContaCorrente
:
public class ContaCorrente : Conta
{
public double CalcularTaxaAdministrativa()
{
return 0;
}
}
Aqui não falamos ao compilador que ContaCorrente
possui a propriedade Saldo
, só dizemos "A ContaCorrente
é uma classe que define um método não-virtual CalcularTaxaAdministrativa
" e aqui vale a mesma coisa, a aplicação, ao ver uma referência do tipo ContaCorrente
já sabe imediatamente qual método chamar e é este que retorna 0
.
Dado que, a partir de cada tipo de referência, a aplicação já sabe qual método executar, temos:
Conta conta = new Conta();
ContaCorrente corrente = new ContaCorrente();
conta.CalcularTaxaAdministrativa(); // 1
corrente.CalcularTaxaAdministrativa(); // 0
Parece razoável? O que acha?
Tudo o que falamos, foi em relação a referências do tipo Conta
e ContaCorrente
. Sabemos que, graças ao polimorfismo, podemos guardar um objeto do tipo ContaCorrente
em uma referência do tipo Conta
:
Conta conta = new ContaCorrente();
agora a saída de conta.CalcularTaxaAdministrativa();
será 1
! E isso é porque estamos chamando o método CalcularTaxaAdministrativa
a partir de uma referência do tipo Conta
e, como falamos lá em cima, a aplicação (mais especificamente, a máquina virtual CLR) sabe exatamente qual método deve ser executado ao encontrar uma Conta
- ele nem vai verificar o tipo do objeto e verificar os métodos da ContaCorrente
, porque não existe outra opção.
Ótimo, agora, vamos ao caso em que usamos o virtual
e o override
:
public class Conta
{
...
public virtual double CalcularTaxaAdministrativa() { ... }
}
public class ContaCorrente : Conta
{
...
public override double CalcularTaxaAdministrativa() { ... }
}
Aqui falamos "A classe Conta
possui um método virtual chamado CalcularTaxaAdministrativa
" e agora as coisas mudaram. Como este método é virtual, a CLR não sabe exatamente qual método deverá executar com estas referências, então aqui haverá mais cuidado.
Também falamos "A classe ContaCorrente
sobrescreve o método CalcularTaxaAdministrativa
definido na classe base".
Agora, vamos ver o código abaixo:
Conta conta = AlgumMetodoQueDevolveUmaConta();
conta.CalcularTaxaAdministrativa();
(continua na próxima resposta)
(continuando)
Agora, vamos ver o código abaixo:
Conta conta = AlgumMetodoQueDevolveUmaConta();
conta.CalcularTaxaAdministrativa();
O que acontece nesta chamada? A CLR não sabe logo de cara! Depende do tipo do objeto retornado em AlgumMetodoQueDevolveUmaConta
. Avisamos lá em cima que o método CalcularTaxaAdministrativa
é virtual, então a aplicação não pode imediatamente visitar o tipo Conta
e executar aquele código, afinal, este método pode ter sido sobrescrito em alguma classe derivada, então, somente quando avisamos que o método é virtual
, a CLR vai verificar se o tipo do objeto possui uma sobrescrita neste método. Caso a sobrescrita não tenha sido feita, a CLR irá verificar se a classe derivada sobrescreveu e assim por diante, até chegarmos na definição em Conta
.
Em resumo, quando não usamos virtual
ou override
:
Conta conta = new Conta();
ContaCorrente corrente = new ContaCorrente();
conta.CalcularTaxaAdministrativa(); // Opa, vou executar o método em `Conta`
corrente.CalcularTaxaAdministrativa(); // Opa, vou executar o método em `ContaCorrente`
Conta teste = corrente;
teste.CalcularTaxaAdministrativa(); // Opa, vou executar o método em `Conta`!
Em resumo, quando usamos virtual
ou override
:
Conta teste = new ContaCorrente();
teste.CalcularTaxaAdministrativa(); // Puts, este método foi definido como `virtual`.
// Só vou saber qual método devo executar quando, em tempo de execução,
// eu verificar o tipo do objeto em `teste` e checar se houve uma sobrescrita!
Beleza? Bacana você ter perguntado. Este assunto é um pouco complicado mesmo. O que você acha? Fez sentido?
Abs.