Devo implementar uma interface diretamente ou a superclasse faz isso?

14

Existe alguma diferença entre

public class A extends AbstractB implements C
{...}

versus...

public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}

Entendo que, em ambos os casos, a classe A terminará em conformidade com a interface. No segundo caso, AbstractBpode fornecer implementação para métodos de interface no C. Essa é a única diferença?

Se eu não quiser fornecer uma implementação para qualquer um dos métodos de interface em AbstractB , qual o estilo que eu deveria estar usando ? O uso de um ou de outro tem algum objetivo oculto de 'documentação'?

c_maker
fonte
3
sugestão sobre o título: devo implementar uma interface diretamente ou fazer com que a superclasse faça isso
Jeanne Boyarsky

Respostas:

20

Tudo depende se AbstractB implements Csemanticamente. Ou seja, se faz sentido semanticamente para AbstractBimplementar C, então vá em frente.

Se tomarmos exemplos concretos, a diferença semântica se torna clara.

Se A = Cão, AbstratoB = Animal, C = IBark

A única escolha que faz sentido é

class Dog extends Animal implements IBark{

Isso não faz sentido, pois isso implica que todos os animais latem.

class Animal implements IBark{

As outras diferenças entram em jogo se você tiver mais do que apenas class Aherdar AbstractB. No # 1 eles não precisam implementar C, no # 2 são todos forçados a implementar C.

Karthik T
fonte
1
+1 Muito mais claro do que minha resposta!
Hand-E-Food
Além disso, se a interface foi Heterotroph, parece razoável Animalimplementar Heterotroph. Se você espera muitos outros animais latindo e deseja tratá-los da mesma maneira, outra classe BarkingAnimal extends Animal implements IBarkseria o caminho a seguir.
precisa
@scarfridge Na verdade, eu esperaria animal para estender Heterotrophmas graças para a sua entrada
Karthik T
2

A maneira mais fácil de determinar o relacionamento de herança adequado não é examinar as próprias classes, mas o código que chama métodos nessas classes. Em algum lugar do seu código, você tem algo como AbstractB b = new A();ou otherObject.addAbstractB(this);. De qualquer forma, mais tarde você usará essa AbstractBreferência para fazer várias chamadas de método.

Nessa situação, você deseja chamar métodos C? Se sim, então AbstractBdeve implementar C. Se não, não deveria. Se você não tiver nenhuma situação como essa, não precisará de herança e deve refatorar para usar a composição, pois é muito mais flexível.

Karl Bielefeldt
fonte
2

Não é uma finalidade de documentação "oculta". Permite converter AbstractB e todas as subclasses em C. Na verdade, existem três estilos.

public class A extends AbstractB implements C
public class AbstractB

Eu usaria este se o AbstractB não implementasse C. logicamente. Mesmo que não forneça os métodos, pode ter significado. Tal como o cão estende os implementos animais Wag. Não faz sentido para todos os animais abanar. Observe que essa abordagem não impede realmente o AbstractB de fornecer a implementação.

public class A extends AbstractB
public AbstractB implements C

Eu usaria este se quisesse que todas as subclasses implementassem a interface E faz sentido que todas elas o façam. Como o Beagle estende o AbstractDog implementa o Wag.

public class A extends AbstractB implements C
public class AbstractB implements C

Este é redundante, mas pode adicionar clareza.

Jeanne Boyarsky
fonte
Eu acho que "AbstractC" (que não existe na pergunta) no segundo parágrafo deve ser alterado para "AbstractB". Não consigo editar para fazer isso, pois os editores devem ter pelo menos 6 caracteres.
Cellepo