No soy un chico de C ++, pero me veo obligado a pensar en esto. ¿Por qué es posible la herencia múltiple en C ++, pero no en C #? (Sé del problema del diamante , pero eso no es lo que pregunto aquí). ¿Cómo resuelve C ++ la ambigüedad de firmas de métodos idénticas heredadas de múltiples clases base? ¿Y por qué el mismo diseño no está incorporado en C #?
c#
c++
language-design
multiple-inheritance
Sandeep
fuente
fuente
Respuestas:
Creo (sin tener una referencia dura), que en Java querían limitar la expresividad del lenguaje para hacer que el lenguaje sea más fácil de aprender y porque el código que usa la herencia múltiple es a menudo demasiado complejo por su propio bien. Y debido a que la herencia múltiple completa es mucho más complicada de implementar, también simplificó mucho la máquina virtual (la herencia múltiple interactúa especialmente mal con el recolector de basura, porque requiere mantener los punteros en el medio del objeto (al comienzo de la base) )
Y al diseñar C #, creo que analizaron Java, vieron que la herencia múltiple completa no se perdió mucho y eligieron mantener las cosas simples también.
Lo hace no . Existe una sintaxis para llamar al método de clase base desde una base específica explícitamente, pero no hay forma de anular solo uno de los métodos virtuales y si no anula el método en la subclase, no es posible llamarlo sin especificar la base clase.
No hay nada que incorporar.
Como Giorgio mencionó los métodos de extensión de interfaz en los comentarios, explicaré qué son los mixins y cómo se implementan en varios idiomas.
Las interfaces en Java y C # se limitan solo a los métodos de declaración. Pero los métodos deben implementarse en cada clase que hereda la interfaz. Sin embargo, existe una gran clase de interfaces, donde sería útil proporcionar implementaciones predeterminadas de algunos métodos en términos de otros. El ejemplo común es comparable (en pseudo-idioma):
La diferencia con la clase completa es que esto no puede contener ningún miembro de datos. Hay varias opciones para implementar esto. Obviamente, la herencia múltiple es una. Pero la herencia múltiple es bastante complicada de implementar. Pero no es realmente necesario aquí. En cambio, muchos idiomas implementan esto al dividir el mixin en una interfaz, que es implementada por la clase y un repositorio de implementaciones de métodos, que se inyectan en la clase o se genera una clase base intermedia y se colocan allí. Esto se implementa en Ruby y D , se implementará en Java 8 y se puede implementar manualmente en C ++ utilizando el patrón de plantilla curiosamente recurrente . Lo anterior, en forma CRTP, se ve así:
y se usa como:
Esto no requiere que nada se declare virtual como lo haría la clase base regular, por lo que si la interfaz se usa en plantillas deja abiertas opciones útiles de optimización. Tenga en cuenta que en C ++ esto probablemente todavía se heredaría como segundo padre, pero en lenguajes que no permiten herencia múltiple se inserta en la cadena de herencia única, por lo que es más como
La implementación del compilador puede o no evitar el envío virtual.
Se seleccionó una implementación diferente en C #. En C #, las implementaciones son métodos estáticos de clase completamente separada y la sintaxis de llamada al método es interpretada adecuadamente por el compilador si no existe un método de nombre dado, pero se define un "método de extensión". Esto tiene la ventaja de que los métodos de extensión se pueden agregar a la clase ya compilada y la desventaja de que dichos métodos no se pueden anular, por ejemplo, para proporcionar una versión optimizada.
fuente
La respuesta es que no funciona correctamente en C ++ en caso de conflictos de espacio de nombres. Mira esto . Para evitar conflictos de espacio de nombres, debe hacer todo tipo de giros con punteros. Trabajé en MS en el equipo de Visual Studio y, al menos en parte, la razón por la que desarrollaron delegación fue para evitar la colisión del espacio de nombres por completo. Previamente, había dicho que también consideraban que las Interfaces eran parte de la solución de herencia múltiple, pero me equivoqué. Las interfaces son realmente sorprendentes y pueden hacerse funcionar en C ++, FWIW.
La delegación aborda específicamente la colisión del espacio de nombres: puede delegar en 5 clases y las 5 exportarán sus métodos a su alcance como miembros de primera clase. En el exterior mirando en este ES herencia múltiple.
fuente