¿Debo implementar una interfaz directamente o hacer que la superclase lo haga?

14

¿Hay alguna diferencia entre

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

versus...

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

Entiendo que en ambos casos, la clase A terminará conforme a la interfaz. En el segundo caso, AbstractBpuede proporcionar implementación para métodos de interfaz en C. ¿Es esa la única diferencia?

Si NO deseo de proporcionar una implementación para cualquiera de los métodos de interfaz en AbstractB , qué estilo debo utilizar ? ¿Usar uno u otro tiene algún propósito oculto de 'documentación'?

c_maker
fuente
3
sugerencia sobre el título: ¿debería implementar una interfaz directamente o hacer que la superclase lo haga?
Jeanne Boyarsky

Respuestas:

20

Todo depende de si AbstractB implements Csemánticamente. Es decir, si tiene sentido semánticamente para AbstractBimplementar C, entonces adelante.

Si tomamos ejemplos concretos, la diferencia semántica se vuelve clara.

Si A = Perro, Resumen B = Animal, C = IBark

La única opción que tiene sentido es

class Dog extends Animal implements IBark{

Esto no tiene sentido, ya que esto implicaría que todos los animales ladran.

class Animal implements IBark{

Las otras diferencias entran en juego si tienes más que solo class Aheredar de AbstractB. En el n. ° 1 no necesitan implementar C, en el n. ° 2 todos están obligados a implementar C.

Karthik T
fuente
1
+1 ¡Mucho más claro que mi respuesta!
Hand-E-Food
Además, si la interfaz fuera Heterotrophrazonable, parece razonable Animalimplementarla Heterotroph. Si espera muchos otros animales que ladran y quiere tratarlos de la misma manera, otra clase BarkingAnimal extends Animal implements IBarksería el camino a seguir.
scarfridge
@scarfridge En realidad, esperaría que el animal se extienda, Heterotrophpero gracias por tu aporte
Karthik T
2

La manera fácil de determinar la relación de herencia adecuada no es mirar las clases en sí mismas, sino el código que llama a los métodos en esas clases. En algún lugar de tu código tienes algo como AbstractB b = new A();o otherObject.addAbstractB(this);. De cualquier manera, luego usa esa AbstractBreferencia para hacer varias llamadas a métodos.

En esa situación, ¿vas a querer llamar a métodos de C? Si es así, entonces AbstractBdebe implementar C. Si no, no debería. Si no tiene situaciones como esa, entonces no necesita herencia, y debe refactorizar para usar la composición en su lugar porque está mucho más suelto.

Karl Bielefeldt
fuente
2

No es un propósito de documentación "oculta". Le permite emitir AbstractB y todas sus subclases a C. En realidad, hay tres estilos.

public class A extends AbstractB implements C
public class AbstractB

Usaría este si AbstractB no implementara lógicamente C. Incluso si no proporciona los métodos, podría tener sentido. Tales como perro extiende implementos animales Wag. No tiene sentido para todos los animales Wag. Tenga en cuenta que este enfoque en realidad no impide que AbstractB proporcione la implementación.

public class A extends AbstractB
public AbstractB implements C

Usaría este si quisiera que todas las subclases implementen la interfaz Y tiene sentido que todos lo hagan. Tal como Beagle extiende AbstractDog implementa Wag.

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

Este es redundante pero podría agregar claridad.

Jeanne Boyarsky
fuente
Creo que "AbstractC" (que no existe en la pregunta) en el segundo párrafo debería cambiarse a "AbstractB". No puedo editar para hacerlo, ya que los editores deben tener al menos 6 caracteres.
cellepo