2008-12-18 14 views
12

No estoy muy seguro de cómo título de esta pregunta, pero, básicamente, tengo una interfaz como esta:Diseño de herencia utilizando Interface + clase abstracta. ¿Buena práctica?

public interface IFoo 
{ 
    string ToCMD(); 
} 

un par de clases que implementan absract IFoo como:

public abstract class Foo : IFoo 
{ 
    public abstract string ToCMD(); 
} 

public abstract class Bar : IFoo 
{ 
    public abstract string ToCMD(); 
} 

continuación, las clases que heredan foo y Bar:

public class FooClass1 : Foo 
{ 
    public override string ToCMD() 
    {return "Test";} 
} ///there are about 10 foo classes. 

public class BarClass : Bar 
{ 
    public override string ToCMD() 
    {return "BarClass";} 
} ///about the same for bar classes. 

que estoy haciendo esto para que cuando tenga mi lista personalizada como:

public class Store<T> : List<T> where T : IFoo {} 

Luego puedo restringir los tipos que entran pero al tener la interfaz todavía tomará cualquier tipo de IFoo.

Algo así como:

Store<Foo> store = new Store<Foo>(); //Only Foo types will work. 
store.Add(new FooClass1()); //Will compile. 

Store<IFoo> store = new Store<IFoo>(); //All IFoo types will work. 
store.Add(new FooClass1()); //Will compile. 
store.Add(new BarClass()); //Will compile. 

Mi pregunta es: ¿Es esta una forma aceptable de ir sobre esto? ¿O hay un mejor camino?

EDIT: Imagen-> alt text

Respuesta

6

La necesidad de una cadena de herencia es cuestionable, en general.

Sin embargo, el escenario específico de la combinación de una clase base abstracta con una interfaz .. lo veo de esta manera:

Si usted tiene una clase base abstracta como ésta, también debe tener una interfaz correspondiente. Si tiene una interfaz, entonces use la clase base abstracta solo donde la cadena de herencia es sensata.

Dicho esto, si estoy escribiendo una biblioteca y esto es parte de mi API/Framework, generalmente incluiré una "implementación predeterminada" que se puede usar como una clase base. Implementará los métodos de interfaz de una manera ingenua y general, cuando sea posible, y dejará el resto para que los herederos implementen o anulen según sea necesario.

Sin embargo, esta es solo una función de conveniencia de la biblioteca, para ayudar a las personas que desean implementar la interfaz proporcionando un ejemplo funcional que ya cubre la mayor parte de lo que necesitan implementar.

En resumen, la interfaz es más valiosa que la clase base, pero una clase base puede ahorrar mucho tiempo y reducir las implementaciones de interfaz con errores.

1

Bueno, eso es lo que la palabra clave es donde para. Probablemente necesites evaluar tu modelo de objetos para asegurarte de que la profundidad de tu herencia es necesaria. Las jerarquías de herencia profunda tienden a complicar los proyectos y generalmente son una señal de alerta, pero dependen de la situación.

Normalmente, no necesita la clase abstracta para llevar a cabo la funcionalidad de la que habla con las listas, y las interfaces son el método "preferido" para especificar restricciones de tipo. Solo usaría la versión abstracta de su clase si hay una funcionalidad común que quiera encapsular.

Respuesta corta: asegúrate de que no te va la herencia loca.

Espero que ayude!

1

También podría usar interfaces. No hay ninguna razón para usar una clase abstracta.

public interface Foo : IFoo 
{ 
} 

public interface Bar : IFoo 
{ 
} 
+0

No estaba seguro de que usar interfaces vacías fuera una buena idea. ¿Lo es? –

+0

@ [Nathan W]: no tiene sentido en una interfaz vacía, creo que gcores estaba siendo sucinta –

+0

Eso es lo que pensé, pero solo estaba revisando. –

0

No estoy muy seguro de si esto es lo que está buscando, pero tal vez lo que quiere hacer es la chatarra de la interfaz de todos juntos y hacer esto:

abstract class Base 
{ 
    public abstract string ToCMD(); 
} 

abstract class Foo : Base { } 

abstract class Bar : Base { } 

Esperamos que tengan otros miembros de las clases Foo y Bar! Esto le permitirá restringir su colección personalizada por Base o simplemente utilizar un simple List<Base>.

1

necesita la interfaz; puede o no necesitar la clase abstracta.

En general, si puede proporcionar un comportamiento útil en una clase base, proporcione una clase base; si la clase base no está completo por sí mismo a continuación, hacer que sea abstracta (MustInherit en la jerga VB)

de otro modo, la interfaz es suficiente

Cuestiones relacionadas