[quote=juliocbq][quote=joaoabi]O título do Post que diz (“Prefira composição ao invés de herança”), que conforme o autor disse é uma frase bastante divulgada já explica um pouco a questão,
de verdade quando os livros e apostilas dizem que devemos preferir a composição não quer dizer que esta substitui a herança.
“Uma coisa é uma coisa outra coisa é outra coisa.”
A herança apresenta alguns problemas como por exemplo
I - O encapsulamento entre classes e subclasses é fraco (o acoplamento é forte)
II - Mudar uma superclasse pode afetar todas as subclasses
Isso vai contra um princípio básico de projeto O-O. (manter fraco acoplamento). Às vezes um objeto precisa ser de uma classe diferente em momentos diferentes.
Com herança, a estrutura está parafusada no código e não pode sofrer alterações facilmente em tempo de execução logo vemos que
a herança é um relacionamento estático que não muda com tempo.
Por outro lado o uso de composição nos traz:
Em vez de codificar um comportamento static, podemos definir comportamentos menores por padrão e usarmos a composição para definir os comportamentos mais complicados
Via de regra, a composição é melhor do que herança normalmente, porque, permite mudar as associações entre classes em tempo de execução, permite que um objeto assuma mais de um comportamento:
Ao passo que a Herança acopla as classes demais e engessa o programa[/quote]
Manter fraco o acoplamento não tem nada a ver com usar herança. As classes herdadas mantém o acoplamento necessário entre elas(são “herdadas”). O objetivo é que a hierarquia passe a frente as alterações feitas lá em cima.
As classes que são herdadas e as que herdam mantém esse relacionamento específico, tanto é que toda api java utiliza delas. Se voce precisar de acoplamento fraco voce cria um objeto distinto para realizar uma tarefa.
Como disse essa frase é muito divulgada mas eu acabo não concordando com ela. Composição e Herança são usadas para resolver problemas diferentes.
[/quote]
Composição e herança deveriam ser usadas para resolver problemas diferentes, mas na prática não são. Existem sim esse hábito de atrelar comportamentos, que poderiam e deveriam ser independentes uns dos outros, através da herança.
Por exemplo, imagine que eu preciso implementar uma classe que calcula juros, porém antes de calcular os juros de uma dívida eu preciso levantar o valor original dessa divida. Para isso eu já tenho lá a classe DividaOriginal que faz esse levantamento completo. Agora para calcular os juros ao invés de usar o DividaOriginal como um atributo da minha classe CalculoDeJuros, eu para não ter que arrumar o terreno pra isso, refatorar o que for preciso pra fazer essa composição, opto pelo caminho “mais curto” de herdar de DividaOriginal e implementar o CalculoDeJuros na minha subclasse.
Daí você já pode imaginar como ficarão as coisas quando eu precisar calcular correção, multa, acréscimos de serviços de cobrança e etc…
E é desse tipo de coisa que se fala quando se diz “prefira composição ao invés de herança”, não é uma tentativa de abolir a prática da herança, mesmo quando ela é a melhor solução. Ninguém está dizendo que não se deve usar herança nunca.
Por isso eu estranhei bastante quando vocês falaram que não conseguiam ver a relação entre as duas coisas. Evidente que em seus conceitos elas são coisas diferentes, o que me surpreende é o fato de vocês nunca as terem visto confundidas.