Q. Ao executar este código:
Conta c = new ContaPoupanca();
Estou criando uma referência para a classe Conta do tipo ContaPoupanca?
R. Sim. Essa ideia de uma variável conseguir referenciar seu próprio tipo ou filhos desse tipo é conhecido por polimorfismo.
Q. Como a variável c é do tipo conta então só herda os métodos e atributos da Conta. Então qual a utilidade do código Conta c = new ContaPoupanca();?
R. Não. a variável c que foi criada: Conta c = new ContaPoupanca(); é do tipo ContaPoupanca, neste caso c herdou os métodos e atributos de Conta.
Ainda não fiz esse curso, mas estarei assumindo a ideia de que você tem uma classe chamada Conta que tem atributos e métodos que são comuns a ContaCorrente e ContaPoupanca - ou seja - essas duas últimas herdam dessa classe pai chamada Conta todo o código em comum (definição de herança). Espero que até aí esteja tudo bem.
Além da reutilização de código, existe a possibilidade de escrever métodos que podem receber argumentos tanto do tipo ContaCorrente quanto do tipo ContaPoupanca, utilizando o que se chama neste caso de polimorfismo. Basta fazermos os métodos referenciarem o tipo mais genérico, no caso, Conta.
Mas o que acontece quando executamos a seguinte linha:
Conta c = new Conta();
Criamos um novo objeto do tipo Conta.
Mas esse objeto faz algum sentido para nossas regras de negócio?
Como falei é uma conta genérica, o que da p'ra perceber que ela acaba não sendo nem conta corrente e nem poupança. Neste caso, não deveria nem permitir a instanciação de objetos Conta. Por isso eu creio que no seu caso Conta, seja uma classe abstrata.
public abstract class Conta
{
// ...
}
Sendo assim, Conta é apenas uma ideia em seu domínio, uma forma genérica de referenciarmos os dois tipos de conta que realmente existem em um sistema, ContaCorrente e ContaPoupanca
Estão, se a classe Conta está da seguinte forma:
public abstract class Conta
{
// ...
}
Você não vai poder mais criar objetos do tipo Conta, mas vai poder usar variáveis do tipo conta, para referenciar objetos de outros tipos:
Exemplo:
Conta conta = new Conta(); //não compila, e não pode criar objetos abstratos
Conta cc = new ContaCorrente(); // pode, objeto criado é do tipo ContaCorrente
Conta cp = new ContaPoupanca(); // pode, objeto criado é do tipo ContaPoupanca
Não sei se fui claro, mas de uma pesquisada sobre Polimorfismo que pode ajudar a entender melhor este assunto.