¿Cuándo usar clases abstractas en lugar de interfaces con métodos de extensión en C #?

69

"Clase abstracta" e "interfaz" son conceptos similares, siendo la interfaz el más abstracto de los dos. Un factor diferenciador es que las clases abstractas proporcionan implementaciones de métodos para clases derivadas cuando es necesario. Sin embargo, en C #, este factor de diferenciación se ha reducido con la reciente introducción de métodos de extensión, que permiten proporcionar implementaciones para los métodos de interfaz. Otro factor diferenciador es que una clase puede heredar solo una clase abstracta (es decir, no hay herencia múltiple), pero puede implementar múltiples interfaces. Esto hace que las interfaces sean menos restrictivas y más flexibles. Entonces, en C #, ¿cuándo deberíamos usar clases abstractas en lugar de interfaces con métodos de extensión?

Un ejemplo notable del modelo de interfaz + método de extensión es LINQ, donde se proporciona la funcionalidad de consulta para cualquier tipo que implemente IEnumerable a través de una multitud de métodos de extensión.

    
pregunta Gulshan 31.01.2011 - 10:17

7 respuestas

61

Cuando necesitas una parte de la clase para ser implementada. El mejor ejemplo que he usado es el método de plantilla .

public abstract class SomethingDoer
{
    public void Do()
    {
        this.DoThis();
        this.DoThat();
    }

    protected abstract void DoThis();
    protected abstract void DoThat();
}

Por lo tanto, puede definir los pasos que se tomarán cuando se llame a Do (), sin conocer los detalles específicos de cómo se implementarán. Las clases derivadas deben implementar los métodos abstractos, pero no el método Do ().

Los métodos de extensión no necesariamente satisfacen la parte de la ecuación "debe ser parte de la clase". Además, iirc, los métodos de extensión no pueden (aparentemente) ser más que públicos en su alcance.

editar

La pregunta es más interesante de lo que originalmente había dado crédito. Tras un examen más detenido, Jon Skeet respondió una pregunta como esta en SO a favor de utilizando interfaces + métodos de extensión. Además, un potencial inconveniente está utilizando la reflexión en contra de una jerarquía de objetos diseñada de esta manera .

Personalmente, estoy teniendo problemas para ver el beneficio de alterar una práctica común en la actualidad, pero también veo pocas o ninguna desventajas al hacerlo.

Cabe señalar que es posible programar de esta manera en muchos idiomas a través de las clases de Utilidad. Las extensiones solo proporcionan el azúcar sintáctico para hacer que los métodos parezcan que pertenecen a la clase.

    
respondido por el Steven Evers 31.01.2011 - 11:15
24

Se trata de lo que quieres modelar:

Las clases abstractas funcionan por herencia . Al ser solo clases base especiales, modelan una relación is-a .

Por ejemplo, un perro es un animal, por lo tanto tenemos

class Dog : Animal { ... }

Como no tiene sentido en realidad crear un animal genérico (¿qué aspecto tendría?), creamos este Animal clase base abstract , pero sigue siendo un clase base Y la clase Dog no tiene sentido sin ser un Animal .

Interfaces , por otro lado, es una historia diferente. No utilizan la herencia, pero proporcionan polimorfismo (que puede también se puede implementar con herencia). No modelan una relación is-a , pero más de un es compatible .

Toma por ej. IComparable : un objeto que admite la comparación con otro .

La funcionalidad de una clase no depende de las interfaces que implementa, la interfaz solo proporciona una forma genérica de acceder a la funcionalidad. Todavía podríamos Dispose de un Graphics o un FileStream sin tener que implementar IDisposable . La interfaz simplemente relaciona los métodos juntos.

En principio, uno podría agregar y eliminar interfaces al igual que las extensiones sin cambiar el comportamiento de una clase, simplemente enriqueciendo el acceso a ella. ¡No se puede quitar una clase base, ya que el objeto perdería su significado!

    
respondido por el Dario 31.01.2011 - 13:13
3

Acabo de darme cuenta de que no he usado clases abstractas (al menos no creadas) en años.

La clase abstracta es una bestia algo extraña entre la interfaz y la implementación. Hay algo en las clases abstractas que estremece mi sentido de la araña. Yo diría que, uno no debe "exponer" la implementación detrás de la interfaz de ninguna manera (o hacer cualquier enlace).

Incluso si existe la necesidad de un comportamiento común entre las clases que implementan una interfaz, usaría una clase auxiliar independiente, en lugar de una clase abstracta.

Iría por interfaces.

    
respondido por el Maglob 31.01.2011 - 11:06
2

En mi humilde opinión, creo que hay una mezcla de conceptos aquí.

Las clases usan un cierto tipo de herencia, mientras que las interfaces usan un tipo diferente de herencia.

Ambos tipos de herencia son importantes y útiles, y cada uno tiene sus pros y sus contras.

Empecemos por el principio.

La historia con interfaces comienza hace mucho tiempo con C ++. A mediados de la década de 1980, cuando se desarrolló C ++, la idea de las interfaces como un tipo diferente de tipo aún no se había concretado (llegaría a tiempo).

C ++ solo tenía un tipo de herencia, el tipo de herencia utilizada por las clases, llamada herencia de implementación.

Para poder aplicar la recomendación del Libro GoF: "Para programar para la interfaz, y no para la implementación", C ++ admitió clases abstractas y herencia de implementación múltiple para poder hacer lo que las interfaces en C # son capaces (¡y útiles! ) de hacer.

C # introduce un nuevo tipo de tipo, interfaces, y un nuevo tipo de herencia, herencia de interfaz, para ofrecer al menos dos formas diferentes de admitir "Para programar para la interfaz, y no para la implementación", con una advertencia importante : C # solo admite herencia múltiple con herencia de interfaz (y no con herencia de implementación).

Por lo tanto, las razones arquitectónicas detrás de las interfaces en C # son las recomendaciones de GoF.

Espero que esto pueda ser de ayuda.

Saludos cordiales, Gastón

    
respondido por el Gastón E. Nusimovich 03.09.2012 - 17:42
1

La aplicación de métodos de extensión a una interfaz es útil para aplicar un comportamiento común en todas las clases que pueden compartir solo una interfaz común. Es posible que dichas clases ya existan y que estén cerradas a extensiones por otros medios.

Para los nuevos diseños, yo preferiría el uso de métodos de extensión en interfaces. Para una jerarquía de tipos, los métodos de extensión proporcionan un medio para extender el comportamiento sin tener que abrir toda la jerarquía para su modificación.

Sin embargo, los métodos de extensión no pueden acceder a la implementación privada, por lo que en la parte superior de una jerarquía, si necesito encapsular la implementación privada detrás de una interfaz pública, entonces la única manera sería una clase abstracta.

    
respondido por el Ed James 31.01.2011 - 12:24
0

Creo que en C # no se admite la herencia múltiple y es por eso que el concepto de interfaz se introduce en C #.

En el caso de clases abstractas, tampoco se admite la herencia múltiple. Por lo tanto, es fácil decidir si usar clases o interfaces abstractas.

    
respondido por el Beginner 20.12.2012 - 10:49
-1

Estoy en el proceso de implementar una clase abstracta en mi proyecto simplemente porque C # no admite operadores (conversiones implícitas, en mi caso) en Interfaces.

    
respondido por el palswim 30.05.2012 - 22:48

Lea otras preguntas en las etiquetas