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(); // 0Parece 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.