Podemos referenciar classes que implementam essa interface, por exemplo: ITributavel t = new ContaPoupanca();
Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!
Podemos referenciar classes que implementam essa interface, por exemplo: ITributavel t = new ContaPoupanca();
Olá, Felipe!
a variável de objeto t é do tipo ITributavel, ou seja, ela só pode conter objetos de classes que implementam a interface ITributavel.
Podemos escrever:
ITributavel t = new ContaPoupanca();
Mas também poderíamos escrever
ContaPoupanca t = new ContaPoupanca();
As duas maneiras estão corretas. Mas qual a diferença? A diferença é que ITributavel t pode conter ContaPoupanca, mas também poderia conter objeto de outra classe que implementa ITributavel, como por exemplo ContaCorrente:
ITributavel t = new ContaCorrente();
Essa forma acima também está certa! Agora, o que acontece se escrevermos:
ContaPoupanca t = new ContaCorrente();
?
Nesse caso, teremos um erro de compilação, pois a declaração ContaPoupanca t nos obriga a instanciarmos um objeto do tipo específico ContaPoupanca. Não podemos atribuir um ContaCorrente a uma variável que foi definida como outro tipo.
Pense dessa forma: a variável declarada como ITributavel é mais "genérica", mais "tolerante" e "flexível". Uma variável declarada como ContaPoupanca é mais "específica", "exigente" e "inflexível".
Espero ter ajudado. Boa sorte e bons estudos!
Boa tarde Felipe,
Baseado nesta ótima resposta do Marcelo, pense o seguinte: o Polimorfismo é a capacidade de um objeto ter várias formas não é? Vamos enxergar o polimorfismo desta situação:
ContaPoupanca pode ser instanciada, e este objeto pode ser referenciado por várias formas, como por exemplo:
Conta c = new ContaPoupanca(); //assumindo que há uma herança aqui
// e também
ITributavel t = new ContaPoupanca();
Com essa flexibilidade explicada pelo Marcelo, você ganha algo muito poderoso: a capacidade de implementar comportamentos que teriam que ocorrer para diversos objetos escrevendo um código genérico, exemplo:
public void calcularTributo(ITributavel tributavel) {
// lógica de calcular um tributo
}
O cálculo de um Tributo ocorre para uma ContaPoupanca? Sim. Então basta passar ela para o objeto que faz isso, e devido ao contrato com a interface será possível realizar o comportamento. Agora ContaCorrente também tem tributo? Sim. Basta assinar o contrato com a interface que vai servir. Agora Cheque (que nem é um tipo de Conta) tem tributo? Mesma coisa. Assina o contrato com a interface e manda bala.
Você não precisará de um objeto que implemente um comportamento próprio para ContaPoupanca, e outro para ContaCorrente, e outro para Cheque, assim:
public void calcularTributo(ContaPoupanca tributavel) {
// lógica de calcular um tributo de ContaPoupanca
}
public void calcularTributo(ContaCorrente tributavel) {
// lógica de calcular um tributo de ContaCorrente
}
public void calcularTributo(Cheque tributavel) {
// lógica de calcular um tributo de Cheque
}
Conseguiu visualizar o que o Polimorfismo traz de vantagem para uma linguagem orientada a objetos? Mais simplicidade no desenvolvimento de uma solução, reaproveitamento de código, não repete coisa que não precisa, etc.
Abraço.