Olá pessoal,
gostaria de saber como vcs estruturariam a solução para a seguinte situação:
1 - Eu tenho uma interface TipoA com alguns métodos que são obrigatórios que todos os objetos que são do TipoA implementem;
2 - Eu tenho uma interface TipoB extends TipoA e TipoC extends TipoA, que estedem a interface TipoA com alguns métodos específicos que os objetos que implementam TipoB e TipoC precisam implementar.
3 - Por fim, tenho as classes TipoBDefault implements TipoB e TipoCDefault implements TipoC. Agora, na implementação dessas classes, a maioria dos métodos provenientes de TipoA possuem uma implementação comum, mas não todos. A pergunta é: onde colocar o código comum? Na minha opinião, o melhor (ou menos pior) seria colocar numa classe abstrata das quais TipoB e TipoC herdam, da seguinte forma:
class TipoBDefault extends AbstractTipoA implements TipoB {
// implementacoes dos metodos declarados em TipoB
}
Mas, como bem observado no comentário do Fabio Kung no blog da Caelum ( http://blog.caelum.com.br/2006/08/26/ei-como-e-o-seu-dao-ele-e-tao-abstraido-quanto-o-meu/ ), este é um mau uso da herança, apenas para reutilização de funcionalidade.
Poderíamos quebrar essa classe abstrata, criando uma outra interface TipoComImplementacaoComum contendo apenas os métodos de TipoA cuja implementação é a mesma para ambas as classes TipoBDefault e TipoCDefault e então, injetamos essa dependência nessas classes, da seguinte forma:
class TipoBDefault implements TipoB {
private TipoComImplementacaoComum implComum;
public TipoBDefault(TipoComImplementacaoComum implComum) {
this.implComum = implComum;
}
public X umMetodoQualquerDeclaradoEmTipoA() {
return implComum.umMetodoQualquerDeclaradoEmTipoA();
}
public Y outroMetodoQualquerDeclaradoEmTipoA() {
return implComum.outroMetodoQualquerDeclaradoEmTipoA();
}
public Z umMetodoQualquerDeclaradoEmTipoAComImplEspecifica() {
// implementação específica
}
public W umMetodoQualquerDeclaradoEmTipoB() {
// implementacao
}
}
Nesta última opção, teríamos a criação de uma interface a mais (mais um .java), com diversos métodos idênticos aos já declarados na interface TipoA (tudo bem, poderíamos fazer TipoA herdar desta outra interface). Sei que o exemplo ficou bem ruim usando esses nomes abstratos, mas, numa situação dessas, a herança a partir de uma classe abstrata não provoca tantos problemas, O que acham?
abraços