¿Por qué los mixins o rasgos son mejores que la simple herencia múltiple?

50

C ++ tiene una herencia múltiple simple, muchos diseños de lenguajes lo prohíben como peligroso. Pero algunos lenguajes como Ruby y PHP usan una sintaxis extraña para hacer lo mismo y llamarlo mixins o rasgos. Escuché muchas veces que los mixins / rasgos son más difíciles de abusar que la simple herencia múltiple.

¿Qué los hace específicamente menos peligrosos? ¿Hay algo que no sea posible con los mixins / rasgos pero es posible con la herencia múltiple de estilo C ++? ¿Es posible encontrar el problema del diamante con ellos?

Esto parece como si estuviéramos usando herencia múltiple, pero solo inventando excusas de que esos son mixins / rasgos para que podamos usarlos.

    
pregunta Gherman 22.07.2014 - 22:32

1 respuesta

30

Hay una serie de problemas con la herencia múltiple cuando se usa con clases de pleno derecho, pero todas giran en torno a ambiguity .

La ambigüedad se manifiesta de diferentes maneras:

  1. Si tiene dos clases base con el mismo campo x , y el tipo derivado solicita x , ¿qué obtiene?
    • Si las dos variables x tienen tipos incongruentes, podría inferirlo.
    • Si son del mismo tipo, podría intentar fusionarlos en la misma variable.
    • Siempre puedes exponerlos como nombres extraños y completamente calificados.
  2. Si tiene dos clases base con la misma función f con firmas idénticas, y alguien llama a f , ¿a quién se llama?
    • ¿Qué sucede si las dos clases base comparten otro ancestro virtual común (el problema del diamante)?
    • ¿Qué sucede si la función tiene firmas diferentes pero compatibles?
  3. Cuando construyes una clase con dos clases base, ¿a cuál de los constructores de las clases base se llama primero? Cuando destruyes el objeto, ¿cuál es el muerto?
  4. Cuando presenta el objeto en la memoria, ¿cómo lo hace de manera coherente?
  5. ¿Cómo maneja todos estos casos con 3 clases base? 10?

Y eso ignora cosas como el envío dinámico, la inferencia de tipos, la coincidencia de patrones y otras cosas que conozco menos que se vuelven más difíciles cuando el idioma admite la herencia múltiple de clases completas.

Las características o combinaciones (o interfaces, o ...) son todas las construcciones que específicamente limitan las capacidades de un tipo para que no haya ambigüedad. Rara vez poseen algo por sí mismos. Esto permite que la composición de tipos sea más suave porque no hay dos variables o dos funciones ... hay una variable y una referencia; Una función y una firma. El compilador sabe qué hacer.

El otro enfoque común es forzar al usuario a "construir" (o mezclar) su tipo uno a la vez. En lugar de que las clases base sean socios iguales en el nuevo tipo, agregue un tipo a otro, anulando todo lo que estaba allí (generalmente con sintaxis opcional para renombrar y / o reexponer los bits anulados).

  

¿Hay algo que no sea posible con los mixins / rasgos pero es posible con la herencia múltiple de estilo C ++?

Según el idioma, generalmente resulta problemático o imposible fusionar implementaciones de las funciones y el almacenamiento de variables de varias clases base y exponerlas en el tipo derivado.

  

¿Es posible encontrarse con un problema de diamante con ellos?

Ocasionalmente, aparecerán variaciones menos graves en función de su idioma, pero generalmente no. Todo el punto de los rasgos es romper ese tipo de ambigüedad.

    
respondido por el Telastyn 22.07.2014 - 23:15

Lea otras preguntas en las etiquetas