Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Em qual situação seria mais vantajosa a referenciação de um objeto pela classe mãe?

Ainda nao consegui identificar uma ocasião em que fosse mais vantajoso usar a referencia mais generica para instanciar um objeto, já que ele só acaba ficando mais limitado aos atributos e métodos da referencia.

Por exemplo, o Objeto instanciado "Funcionario gerente = new Gerente()", se Gerente tiver um construtor que obriga a declaração da variavel senha, como ficaria já que Funcionario não pode acessar senha de Gerente?

6 respostas

Olá Thaina, tudo bem?

Se você precisar de um método/atributo da classe filha não vai ter jeito, tem que utilizar essa classe mesmo, porém a vantagem de utilizar a classe mãe é poder receber vários tipos de objetos e utilizar os métodos compartilhados entre todos eles sem ter que se preocupar em run-time com qual é de fato o tipo desse objeto.

Ainda nao consegui identificar uma ocasião em que fosse mais vantajoso usar a referencia mais generica para instanciar um objeto, já que ele só acaba ficando mais limitado aos atributos e métodos da referencia.

Vou tentar dar um exemplo: Imagine que você está trabalhando no sistema de gestão de uma empresa de desenvolvimento de software. Nessa empresa, os funcionários podem ser: Aprendiz, Desenvolvedor, Techlead, Arquiteto e Gerente. Essa empresa oferece bônus diferente a cada tipo especifico de funcionário, por essa razão, cada classe especifica (que herda da classe Funcionario) implementa seu próprio método de obterValorDoBonus()...

Imagine que foi pedido para você que calcule o valor de bônus total que a empresa vai pagar esse ano. O que seria mais prático, criar 5 método para somar os valores de cada um dos tipos específicos de funcionário:

public double obtemSomaBonusGerente(Gerente[ ] gerentes) {
    return ... soma dos bonus ...
} 

public double obtemSomaBonusArquiteto(Arquiteto[ ] arquitetos) {
    return ... soma dos bonus ...
} 

public double obtemSomaBonusTechlead(Techlead[ ] techleads) {
    return ... soma dos bonus ...
} 

public double obtemSomaBonusDesenvolvedor(Desenvolvedor[ ] desenvolvedores) {
    return ... soma dos bonus ...
} 

public double obtemSomaBonusAprendiz(Aprendiz[ ] aprendizes) {
    return ... soma dos bonus ...
} 

ou algo mais simples como:

public double obtemSomaBonus(Funcionario[ ] funcionarios) {
    return ... soma dos bonus ...
} 

A vantagem da segunda abordagem fica ainda mais clara quando a empresa começa a terma mais "tipos" de funcionários, o mesmo método serve para todos...

Ok, eu consigo identificar a vantagem na hora de reescrever métodos ou atributos em comum.

Minha dúvida está em qual seria a vantagem na hora de INSTANCIAR usando a ref mais genérica. Em qual momento seria mais vantajoso instanciar "Funcionario gerente = new Gerente();" ao invés de simplesmente instanciar "Gerente gerente = new Gerente();".

Não me parece nenhum pouco vantajosa essa maneira de instaciar. Eu sei que existe, mas não sei pra que eu usaria.

No caso visto em outro curso, com Paulo, eu vi uma classe Conta que, entre seus atributos, tinha um atributo do tipo Cliente (outra classe). Não era caso de herança (extends), mas fazia sentido construir uma "Conta conta = new Cliente()"para poder declarar atributos de um objeto que até então não existia, através do objeto conta criado. Mas no caso da herança, pra mim, ainda não vejo vantagens.

A vantagem é o polimorfismo, a garantia de que cada instância de um subtipo (por exemplo Child) pode ser usada como uma instância de seu supertipo (por exemplo Parent). Você tem a garantia de que quando você acessa employee.getEmployeeDetails ou employee.name o método ou campo é definido em qualquer objeto não nulo que possa ser atribuído a uma variável employee do tipo Parent. Para fazer essa garantia, o compilador considera apenas esse tipo estático (basicamente, o tipo da referência de variável, Parent) ao decidir o que você pode acessar. Portanto, você não pode acessar nenhum membro definido no tipo de tempo de execução do objeto, Child.

solução!

Eu avancei um pouco nos cursos e peguei um exemplo útil de instanciar usando uma referência mais genérica que seriam as arrays. Por exemplo:

Conta[] contas = new Contas[5];

No exemplo você poderia armazenar objetos ContaCorrente ou ContaPoupanca. Mas você poderia criar um array da seguinte maneira:

Object[] objetos = new Object[5];

e, nesse exemplo, você também poderia criar e guardar ContaCorrete ou ContaPoupanca. Afinal, pode guardar qualquer coisa que seja um objeto. String, um int ou double, um boolean... Mas aí você ficará limitado aos métodos que todo e qualquer objeto armazenado possa invocar. Exemplo:

objetos[0].toString() ;

é um método que funciona com todo objeto, independente do tipo de objeto armazenada em "objetos[0]". já

ContaCorrente contaCorrente = new ContaCorrente(11, 222);
objetos[0] = contaCorrente;

contaCorrente.depositar(25); // compila
objetos[0].depositar(25)// não compila

apesar de ambos referenciarem o mesmo objeto, são referencias que irão funcionar de maneira diferente. O método "deposita" pertence à ContaCorrente, e não a Object. Ao usar "objetos[0].", eu perco algumas funcionalidades para ganhar outras. Então:

ContaCorrente contaCorrente = new ContaCorrente(11, 222);
objetos[0] = contaCorrente;

objetos[0] = "Não há contas aqui.";

eu posso mudar e armazenar uma String, por exemplo.

Perfeito, ótimo exemplo :)