Herança

Fala pessoal.

Estou com algumas dúvidas quanto a herança. Vou colocar todas nesse post porque aí facilita ao invés de ter que colocar um monte de posts no fórum valeu ?

Seguinte:
-Uma classe filho tem que implementar todos os métodos do pai (override) ? Ou eu só faço isso se eu quiser que o filho não tenha acesso a eles (sem ser por private claro).

-Qual a finalidade de se ter uma referência de superclasse (apontando para uma) em uma de subclasse ? Não seria melhor cada qual com sua própria referência ?

-Eu sei que tem que ser feito, mas não entendi o porque. Porque tem que se ter uma chamada ao construtor da superclasse (implicitamente ou explicitamente) ?

[quote=“JBoy__”]Fala pessoal.

Estou com algumas dúvidas quanto a herança. Vou colocar todas nesse post porque aí facilita ao invés de ter que colocar um monte de posts no fórum valeu ?

Seguinte:
-Uma classe filho tem que implementar todos os métodos do pai (override) ? Ou eu só faço isso se eu quiser que o filho não tenha acesso a eles (sem ser por private claro).

-Qual a finalidade de se ter uma referência de superclasse (apontando para uma) em uma de subclasse ? Não seria melhor cada qual com sua própria referência ?

-Eu sei que tem que ser feito, mas não entendi o porque. Porque tem que se ter uma chamada ao construtor da superclasse (implicitamente ou explicitamente) ?[/quote]

1 - Ter não tem, mas os que ela não implementar serão herdados desde que a acessibilidade permita. E isso não impede que você tenha acesso à eles, na verdade o objetivo é obter os benefícios do polimorfismo.

2 - Polimorfismo

3 - Para garantir que todas as classes na hierarquia de herança (?!) sejam corretamente inicializadas (construidas)

Complementando…

1 - O objetivo de fazer override de um método e mudar seu comportamento em relação a classe pai. Em tempo de execução o Java verifica se o método com tal nome existe na classe filha, se existir, chama ele, caso contrário, chama o da classe pai. Só é obrigatório fazer override caso o método seja abstract. Para acessar o método da superclasse em um método sobrescrito você pode usar o super.

2 - Polimorfismo. Exemplos: você tem um método que pode receber como parâmetro uma List. Não importa para o método se é uma LinkedList, umas ArrayList ou qualquer outra list, pois você pode trabalhar igualmente com elas utilizando os métodos já declarados em List. Então para não ter que fazer um monte de método com todas as possibilidades de listas possíveis (o que seria impossível, já que qualquer pessoa pode implementar List) você faz um método genérico que aceite List. Dentro de métodos você também pode fazer a mesma coisa, pois se algum dia você perceber que por exemplo ArrayList teria uma performance melhor que LinkedList, é só trocar o tipo de objeto construído, podendo manter igual todo o resto do código que utilizava esse objeto.

3 - Toda a hierarquia das classes tem que ser inicializada corretamente porque a subclasse herda todos os membros, então se por exemplo você tem um método que acessa uma variável de instância da superclasse que seria inicializada no contrutor, ela tem que ser inicializada.

Posso ser chato? hein? hein? hein (cutucando)? :smiley:

Nao eh obrigatorio fazer override caso a sua classe filha tambem seja abstrata. Nesse caso, o metodo pode continuar abstrato numa boa :slight_smile:

hahahaha essa do cutucando foi muita onda cv :stuck_out_tongue:
da pra imaginar aqueles pentelho futucando a gente com o dedo :stuck_out_tongue:

Antes de mais nada eu vou logo agradecendo a vocês que tiveram a paciência de responder esse meu post :).Valeu Bani, cv e marciolx.

Agora já que eu agradeci vem mais uma:

Um método de superclasse que foi sobrescrito na subclasse deve ter o mesmo tipo de retorno ok ? Mas a lista de parâmetros do método tem que ser a mesma ?

ps. tomem cuidado não que eu ainda não terminei o capítulo, então vem mais pergunta de herança aí :stuck_out_tongue:

Se a lista de parâmetros for diferente é outro método, pois a assinatura do método é composta pelo seu nome + parâmetros.
Então, se você cria um com parâmetros diferentes, é como se estivesse escrevendo um método totalmente novo, não é um caso de override.

[quote=“Bani”]Se a lista de parâmetros for diferente é outro método, pois a assinatura do método é composta pelo seu nome + parâmetros.
Então, se você cria um com parâmetros diferentes, é como se estivesse escrevendo um método totalmente novo, não é um caso de override.[/quote]

complementado:

a lista de parâmetros de um método neste caso é apenas o tipo do parâmetro, o nome do parâmetro não importa e pode ser diferente porque não faz parte da assinatura do método.

Me desculpem pelo tamanho do post. Mas esse livro de DEITEL complica muito as coisas e eu tenho que tirar isso porque está me deixando confuso.

[Pra quem tiver] Na página 394 ele faz um monte de comparações entre superclasses e subclasses, apontando referencias de superclasses para subclasses e de subclasses para superclasses. Pois bem, ele diz que atribuições de superclasse para subclasses não são permitidas poir é contra os conceitos de herança do tipo “é um” e blá blá blá. Só que chegou numa hora que ele disse que uma referência do tipo filho que aponta pra pai o compilador testa para ver se o método (por exemplo um toString) pode ser utilizado. Minha pergunta é a seguinte. Se o pai não tiver um método (por exemplo um toString) e o filho tiver tem algum problema isso ?

Eu fiz tres classes como exemplo e não teve problema nenhuma. EU ACHO que seja pelo método toString do Object. Mas é só achismo mesmo.

ps. se precisar eu coloco os códigos aqui, só não coloquei pra “encurtar”.

Obrigado

Se você declarar

ClassePai variavel = new ClasseFilha();

E tentar usar variavel.metodoSomenteDaClasseFilha() vai dar pau, porque o compilador vai ver se existe o método na ClassePai, que é o tipo da variável, e não na ClasseFilha. Somente em tempo de execução que será usado o método da ClasseFilha.

Então só recapitulando Bani.

Se eu tiver uma referência de uma superclasse eu posso apontar ela para um objeto de subclasse correto ? MAS, se eu quiser utilizar os métodos da subclasse por essa referência eles tem que constar na superclasse também ?

Me desculpem estar insistindo neste post. Mas como já disse estou neste capítulo do livro e achei uma boa maneira de tirar dúvidas referentes a ele ao invés de ficar postando um monte de mensagens. E também, quem sabe alguem não pode estar aproveitando :shock:

Obrigado.

É isso mesmo.

Oxente… Olha só, se em um relacionamento de herança você não pode utilizar os construtores de uma superclasse e em uma classe abstract você não pode instancias objetos. Tudo bem que uma subclasse que utiliza uma superclasse abstract os construtores são redefinidos na subclasse senão a subclasse se torna abstract.

Qual a finalidade disso então ? Seria pra chamar implicitamente (ou explicitamente) os construtores com super ? Só Isso ? :shock:

Obrigado.

Não é bem assim…
Construtor tem sempre que ter o mesmo nome da classe. Então você nunca vai “redefinir” um construtor em uma subclasse… Você simplesmente vai criar o construtor normal da sua classe. E se não criar nenhum, o compilador cria um automaticamente para você, desde que na superclasse tenha algum construtor sem parâmetros também (ou nenhum construtor, o que dá no mesmo).
Inclusive, você nem pode definir um construtor como abstract. Dá erro de compilação.

Sim, “só isso”. E sinceramente acho que faz muito mais sentido ter o construtor do que proibí-lo só porque a classe é abstrata. Afinal, normalmente eles são utilizados para inicializar variáveis, e isso é perfeitamente natural para uma classe abstrata. E além disso você também pode querer criar um construtor para garantir que a sua classe não terá nenhum construtor sem parâmetros.
A classe ser abstract sigfinica só que você não pode instanciá-la diretamente, mas não deixa de ser um contrato de algo que virá a ser um objeto.