2009-05-30 15 views
6

Similar question but not quite the same thingPseudo-herencia múltiple con métodos de extensión en interfaces en C#?

Estaba pensando que con los métodos de extensión en el mismo espacio de nombres que la interfaz se puede conseguir un efecto similar a la herencia múltiple en el que no deben tener el código duplicado la aplicación de la misma interfaz de la misma manera que en el 10 diferentes clases

¿Cuáles son algunos de los inconvenientes de hacer esto? Creo que los pros son bastante obvios, son los contras los que generalmente vuelven a morderte más adelante.

Uno de los inconvenientes que veo es que los métodos de extensión no pueden ser virtuales, por lo que necesita para asegurarse de que realmente no quiere que implementan la misma manera para todos los casos.

Respuesta

4

El problema que veo con la construcción de capacidad de interfaz a través de métodos de extensión es que ya no están en realidad la implementación de la interfaz y así no se puede utilizar el objeto como el tipo de interfaz.

Supongamos que tengo un método que toma un objeto de tipo IBar. Si implemento la interfaz IBar en la clase Foo a través de los métodos de extensión, entonces Foo no deriva de IBar y no puede usarse indistintamente con él (principio de sustitución Liskov). Claro, obtengo el comportamiento que quiero agregar a Foo, pero pierdo el aspecto más importante de la creación de interfaces en primer lugar: ser capaz de definir un contrato abstracto que puede implementarse de diversas maneras por varias clases para que las clases dependientes no necesitan saber acerca de implementaciones concretas.

Si necesitaba la herencia múltiple (y hasta ahora he vivido sin ella) lo suficiente, creo que haría uso de la composición en vez de reducir al mínimo la cantidad de duplicación de código.

+0

¿Podría explicar "entonces Foo no se deriva de IBar y no se puede usar indistintamente con él"? Si tengo clase pública Foo: IBar, ¿no podría pasar en un Foo en cualquier lugar y se espera un IBar? ¿O quisiste decir algo diferente? Me doy cuenta de que deja de funcionar como una interfaz. Funcionalmente, lo visualizo actuando más como una clase base concreta sin métodos virtuales que una interfaz.(Si es una buena idea o no, posiblemente sea una pregunta aparte, pero parece útil mantener DRY) – Davy8

+0

Y la mayoría de las veces no veo demasiada necesidad de herencia múltiple, pero hay una parte del código en funcionamiento que parece un desastre con el código repetido implementando la misma interfaz en literalmente 10-20 clases diferentes con el mismo código, y no se pudo poner en una clase base porque ya derivan de otra clase base que tiene métodos común a una interfaz diferente. – Davy8

+0

Si Foo se deriva de IBar, entonces necesita tener métodos de instancia, no métodos de extensión que implementen IBar. ¿Esperas delegar estos métodos en los métodos de extensión? Asumí que la implementación fue proporcionada únicamente por las extensiones. Si está haciendo delegación, entonces creo que la composición de las clases base que implementan la funcionalidad de interfaz deseada es más preferible que los métodos de extensión. Tal vez podría proporcionar la funcionalidad utilizando el patrón de decorador. – tvanfosson

1

Una buena manera de pensar acerca de esto es que los métodos de instancia son algo hecho por el objeto, mientras que los métodos de extensión son algo que se hace a el objeto. Estoy bastante seguro de que las Pautas de diseño del marco dicen que debe implementar un método de instancia siempre que sea posible.

Una interfaz declara "Me importa utilizar esta funcionalidad, pero no cómo se logra". Eso deja a los implementadores la libertad de elegir el cómo. Desacopla la intención, una API pública, del mecanismo, una clase con código concreto.

Como este es el principal beneficio de las interfaces, implementarlas por completo como métodos de extensión parece frustrar su propósito. Incluso IEnumerable<T> tiene un método de instancia.

Editar: Además, los objetos están destinados a actuar sobre los datos que contienen. Los métodos de extensión solo pueden ver la API pública de un objeto (ya que son solo métodos estáticos); Tendría que exponer todo el estado de un objeto para que funcione (un OO no-no).

+0

Probablemente he formulado la pregunta mal, pero básicamente no quiero tratarla como una interfaz. La interfaz es simplemente el medio técnico para llevar a cabo la tarea, que es la reutilización de código y la implementación de la herencia múltiple de un pobre en un lenguaje que no lo admite. – Davy8

+0

Ok, veo lo que estás preguntando. En última instancia, le gustaría asociar el comportamiento a las clases que "optan por" mediante la implementación de una interfaz. Múltiples interfaces = comportamientos múltiples = herencia múltiple. Buen razonamiento, pero ¿qué significa? Aún debe exponer el estado de un objeto para que los métodos de extensión puedan funcionar con él. Pero ahora cualquiera puede ver ese estado, entonces no hay encapsulación. Incluso entonces, el método solo obtendrá un IBar, que no tiene miembros, y por lo tanto no es muy útil. ¿Qué podrían hacer los métodos de extensión? Como dijo @tvanfosson, la composición es tu mejor apuesta. –

Cuestiones relacionadas