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

13

¿Hay alguna diferencia entre

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

frente a ...

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

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

Si NO deseo proporcionar una implementación para ninguno de los métodos de interfaz en AbstractB , ¿qué estilo debo usar ? ¿El uso de uno u otro tiene algún propósito oculto de "documentación"?

    
pregunta c_maker 19.12.2012 - 03:12

3 respuestas

18

Todo depende de si AbstractB implements C semánticamente. Es decir, si tiene sentido semánticamente para que AbstractB implemente C , entonces hágalo.

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

Si A = Perro, AbstractB = 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 tiene más de class A heredado de AbstractB . En el # 1 no necesitan implementar C, en el # 2 están obligados a implementar C.

    
respondido por el Karthik T 19.12.2012 - 03:26
2

La forma fácil de determinar la relación de herencia adecuada es no mirar las clases en sí mismas, sino el código que llama 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, más tarde usará esa referencia AbstractB para hacer varias llamadas a métodos.

En esa situación, ¿deseará llamar a los métodos de C ? Si es así, entonces AbstractB debería implementar C . Si no, no debería. Si no tienes situaciones como esa, entonces no necesitas herencia, y deberías refactorizar el uso de la composición porque está mucho más suelto.

    
respondido por el Karl Bielefeldt 19.12.2012 - 05:17
2

No es un propósito de documentación "oculto". Te permite lanzar 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 un significado. Tales como El perro extiende los implementos animales Wag. No tiene sentido para todos los animales a 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 implementaran la interfaz Y tiene sentido que todas lo hagan. Como Beagle extiende AbstractDog implementa Wag.

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

Este es redundante pero puede agregar claridad.

    
respondido por el Jeanne Boyarsky 19.12.2012 - 03:33

Lea otras preguntas en las etiquetas