Eu tenho codificado por cerca de 8 anos, mas ainda acho que a herança é muito flexível e, às vezes, deixa você totalmente confuso com o código que escreveu. Um exemplo mais simples seria:
abstract class AClass {
protected void method1() {
if(check()) {
do1();
} else {
do2();
}
}
protected abstract void do1();
protected abstract void do2();
}
A intenção da classe é que as pessoas possam implementar do1 () e do2 () para que alguma lógica adicional possa ser feita; no entanto, às vezes, as pessoas decidem sobrecarregar o método1 (), e as coisas se complicam imediatamente.
Acho apenas no padrão de estratégia que o código é reutilizado bem por meio da herança; na maioria dos casos, o designer da classe base conhece muito bem suas subclasses, e essa herança é totalmente opcional.
Eu tenho uma classe que é herdada por 4 classes - um IoHandler, e é subclasse para servidor, cliente, servidor de borda, servidor de origem e isso começa a me deixar louco. Eu estava sempre na refatoração de código, sempre tive idéias que acho que funcionariam e depois não foram comprovadas. Dizem que o cérebro humano pode armazenar apenas sete informações uma vez, estou carregando muitas?
fonte
final
[se você estiver usando java]. Isso efetivamente o torna não virtual e não pode ser sobrecarregado. Perfeito para uso nesta circunstância [configuração padrão]Respostas:
Depois de repetir esses padrões, eles não parecem mais tão complicados.
Além disso, você precisa conhecer as classes base antes de herdá-las. E a herança não será opcional enquanto o código comum for reutilizado. Adote qualquer outro padrão, como fábrica / composto abstrato - que a herança realmente serve a um propósito.
Regra prática: não use herança apenas para reunir várias classes. Use-o sempre que fizer sentido. No exemplo artificial, o usuário da classe filho que está sobrecarregando o método1 deve ter algum motivo sério para fazer isso. (OTOH, eu também queria uma maneira de evitar sobrecarregar determinadas funções sozinhas - para evitar isso). E antes de usar essa classe filho, você também deve saber sobre essa peculiaridade. Mas um padrão de estratégia puro não o fará - se o fizer, documente muito bem.
Se você der o seu exemplo de código real, talvez as pessoas aqui possam analisá-lo.
fonte
Sim, pode ser muito complicado ... e você está em boa companhia.
Joshua Bloch em Java efetivo captura bem alguns dos problemas de herança e recomenda favorecer a composição em vez da herança.
fonte
Eu acho que sua pergunta é muito vaga e geral. O que você descreve parece um problema complexo, com ou sem herança. Então, IMHO, é totalmente normal que você esteja lutando contra isso.
Obviamente, em alguns casos, a herança não é a melhor ferramenta para um trabalho (referência obrigatória a "favorecer a composição sobre a herança" ;-). Mas, quando usado com cuidado, acho útil. Pela sua descrição, é difícil decidir se a herança é ou não a ferramenta certa para o seu caso.
fonte
se seus métodos são excessivamente complexos, as subclasses choram
faça com que seus métodos façam uma coisa específica
fonte
A herança de composição restringe o vetor de mudança.
Imagine que sua solução foi implementada e você usa o AClass em 300 locais diferentes da base de código, e agora há um requisito para alterar 45 das chamadas method1 () para que um método do3 () seja chamado em vez de do2 ().
Você pode implementar do3 () no IAnInterface (espero que todas as implementações da interface possam manipular um método do3 () facilmente) e criar uma BClass que chame do1 () ou do3 () na chamada method1 () e altere as 45 referências para o AClass e a dependência injetada.
agora imagem implementando essa mesma alteração para do4 (), do5 (), ...
Ou você pode fazer o seguinte ...
Agora você só precisa implementar uma segunda fábrica que retorne o Doer1 ou o Doer2 e altere a injeção de fábrica em 45 locais. O AClass não muda, o IAnInterface não muda e você pode lidar facilmente com mais alterações como do4 (), do5 ().
fonte
Por que não fazer:
(Eu acho que a final é o equivalente a "selado" em C #, alguém me corrija se essa sintaxe estiver incorreta).
Injeção de dependência / IoC significa que você pode herdar apenas os métodos que realmente deseja que as pessoas possam alterar, o que acho que resolve o seu problema. Além disso, não parece que a classe principal realmente faz o que do1 e do2 são, mais que delega as chamadas em suas subclasses com base em uma condição: você está quebrando a separação de preocupações!
fonte