usar simple porque multiple interfaces implementacion herencia heredar clase c# oop interface multiple-inheritance

simple - ¿Cómo la falta de herencia múltiple de C#llevó a la necesidad de interfaces?



interface c# (4)

En el lenguaje de programación C # Krzysztof Cwalina afirma en una anotación:

decidimos explícitamente no agregar soporte para la herencia múltiple [...] la falta de herencia múltiple nos obligó a agregar el concepto de interfaces, que a su vez son responsables de los problemas con la evolución del marco, las jerarquías de herencia más profundas y muchos otros problemas.

Las interfaces son un concepto central de los lenguajes de programación OO. No sigo el significado de "nos obligó a agregar el concepto de interfaces"

¿Significa Krzysztof que ciertas decisiones de diseño tuvieron que tomarse con respecto al uso de interfaces donde de otro modo se usaría la herencia múltiple? ¿O quiere decir que las interface se introdujeron en C # debido a la falta de herencia múltiple? ¿Puede dar un ejemplo?


Creo que deberías leer lo que dice Eric Lippert sobre Interfaces . Él se ensució las manos, así que creo que él sabe mejor que nadie.

A veces hay peores casos y los peores casos. Tienes que elegir el menos malo.

A continuación hay una copia de la publicación vinculada:

Están ahí solo para asegurarse de que dichas funciones (en la interfaz) se implementen en la clase heredada.

Correcto. Es un beneficio suficientemente impresionante para justificar la función. Como han dicho otros, una interfaz es una obligación contractual de implementar ciertos métodos, propiedades y eventos. El beneficio convincente de un lenguaje estáticamente tipado es que el compilador puede verificar que se cumpla realmente un contrato en el que se basa su código.

Dicho esto, las interfaces son una forma bastante débil de representar las obligaciones contractuales. Si desea una forma más sólida y más flexible de representar las obligaciones contractuales, consulte la función Contratos de código incluida con la última versión de Visual Studio.

C # es un lenguaje excelente, pero a veces te da la sensación de que primero Microsoft crea el problema (no permite la herencia múltiple) y luego proporciona la solución, que es bastante tediosa.

Bueno, me alegra que te guste.

Todos los diseños de software complejos son el resultado de ponderar las características en conflicto entre sí, y de tratar de encontrar el "punto óptimo" que ofrece grandes beneficios para los costos pequeños. A través de la experiencia dolorosa, hemos aprendido que los lenguajes que permiten una herencia múltiple a los fines del intercambio de implementación tienen beneficios relativamente pequeños y costos relativamente grandes. Permitir herencia múltiple solo en interfaces, que no comparten detalles de implementación, brinda muchos de los beneficios de la herencia múltiple sin la mayoría de los costos.


Creo que el lenguaje de Cwalina es un poco fuerte, y no del todo exacto con respecto a la historia.

Recuerde que las interfaces existían antes de C #, por lo que decir "tuvimos que agregar interfaces para resolver el problema x" no me suena bien. Creo que las interfaces habrían estado allí por defecto, tendrían que haber sido.

Además, recuerde que C # se deriva en gran parte de C ++. O, al menos, las personas involucradas en la creación del lenguaje C # tendrían antecedentes muy fuertes en C ++. Herencia múltiple fue un área de pesadilla reconocida en C ++. Heredar de múltiples clases que a su vez pueden derivarse de clases base de commonm, determinar qué implementación tendría prioridad, etc. Quiero decir, es una característica muy poderosa, pero indudablemente puede conducir a código complejo.

Sospecho que abandonaron la herencia múltiple de C # porque ellos (los autores del lenguaje) sabían en qué podía estar todo enredado y querían evitar eso. Tenga en cuenta también que cuando se introdujo C #, uno de sus puntos de venta fue su limpieza (en fairless, no más limpia que Java, pero mucho más limpia que C y C ++).

A propósito, en más de 10 años de desarrollo de C #, solo he deseado la herencia múltiple una vez. Un componente de interfaz de usuario que quería heredar, tanto un estilo visual como un comportamiento común. No me tomó mucho tiempo darme cuenta de que lo que estaba intentando hacer habría sido un diseño bastante horrible en cualquier caso.


De Chris Brumme :

Hay una serie de razones por las cuales no implementamos Herencia de Implementación Múltiple directamente. (Como usted sabe, admitimos herencia de interfaz múltiple).

Creo que lo que dice Krzysztof Cwalina en la cita no es el concepto de las interfaces en sí, sino la herencia de interfaces múltiples como método de herencia múltiple.

Hay varias razones por las que no hemos proporcionado una versión coherente, verificable y compatible con CLS de la herencia de implementación múltiple:

  1. Los diferentes idiomas en realidad tienen diferentes expectativas sobre cómo funciona MI. Por ejemplo, cómo se resuelven los conflictos y si las bases duplicadas se fusionan o son redundantes. Antes de que podamos implementar MI en el CLR, tenemos que hacer una encuesta de todos los idiomas, descubrir los conceptos comunes y decidir cómo expresarlos en una lengua neutral. También tendríamos que decidir si MI pertenece al CLS y lo que esto significaría para los idiomas que no quieren este concepto (presumiblemente VB.NET, por ejemplo). Por supuesto, ese es el negocio en el que nos encontramos como tiempo de ejecución de lenguaje común, pero aún no lo hemos logrado para MI.

  2. El número de lugares donde MI es realmente apropiado es realmente bastante pequeño. En muchos casos, la herencia de interfaz múltiple puede hacer el trabajo en su lugar. En otros casos, es posible que pueda usar encapsulación y delegación. Si tuviéramos que agregar una construcción ligeramente diferente, como mixins, ¿sería realmente más poderosa?

  3. La herencia de implementación múltiple inyecta mucha complejidad en la implementación. Esta complejidad afecta la fundición, el diseño, el despacho, el acceso al campo, la serialización, las comparaciones de identidad, la verificabilidad, la reflexión, los genéricos y, probablemente, muchos otros lugares.


Una interfaz es simplemente una clase base que no tiene miembros de datos y solo define métodos public abstract . Por ejemplo, esto sería una interfaz en C ++:

class IFrobbable { public: virtual void Frob() = 0; }

Por lo tanto, cuando MI está disponible como función de idioma, puede "implementar" interfaces simplemente derivando de ellas (nuevamente, C ++):

class Widget : public IFrobbable, public IBrappable { // ... }

La herencia múltiple en el caso general da lugar a muchas preguntas y problemas que no necesariamente tienen una sola respuesta, o incluso una buena para su definición particular de "bueno" (¿ diamante temido , alguien?). La implementación de múltiples interfaces elude la mayoría de estos problemas exactamente porque el concepto de "heredar" una interfaz es un caso especial muy limitado de heredar una clase en toda regla.

Y aquí es donde aparece "forzado a agregar el concepto de interfaces": no se puede hacer mucho diseño de OO cuando se limita a una sola herencia, por ejemplo, hay problemas serios al no poder volver a usar el código cuando la reutilización de código es de hecho de los argumentos más comunes para OO. Debe hacer algo más, y el siguiente paso es agregar herencia múltiple, pero solo para las clases que satisfacen las restricciones de una interfaz.

Entonces, interpreto la cita de Krzysztof diciendo

La herencia múltiple en el caso general es un problema muy espinoso que no podríamos abordar de manera satisfactoria debido a las limitaciones de la vida real en el desarrollo de .NET. Sin embargo, la herencia de interfaz es mucho más simple de abordar y de suprema importancia en OOP, así que lo hicimos. Pero, por supuesto, las interfaces también vienen con su propio conjunto de problemas, principalmente con respecto a cómo está estructurado el BCL.