En el mundo de Java (más precisamente si no tiene herencia múltiple / mixins) la regla general es bastante simple: "Favorecer la composición de objetos sobre la herencia de clases".
Me gustaría saber si / cómo se cambia si también considera los mixins, especialmente en scala.
¿Los mixins se consideran una forma de herencia múltiple o más composición de clases?
¿Existe también una pauta de "Favorecer la composición de objetos sobre la composición de clases" (o al revés)?
He visto bastantes ejemplos en los que las personas usan (o abusan) de mixins cuando la composición de objetos también podría hacer el trabajo y no siempre estoy seguro de cuál es mejor. Me parece que se pueden lograr cosas bastante similares con ellos, pero también hay algunas diferencias, algunos ejemplos:
- Visibilidad: con mixins, todo pasa a formar parte de la API pública, lo que no ocurre con la composición.
- verbosidad: en la mayoría de los casos, los mixins son menos detallados y un poco más fáciles de usar, pero no siempre es así (por ejemplo, si también usa tipos propios en jerarquías complejas)
Sé que la respuesta corta es "Depende", pero probablemente haya alguna situación típica en la que esto o aquello sea mejor.
Algunos ejemplos de pautas que se me han ocurrido hasta ahora (suponiendo que tenga dos rasgos A y B y que A quiera usar algunos métodos de B):
- Si desea extender la API de A con los métodos de B, entonces mixins, de lo contrario composición. Pero no ayuda si la clase / instancia que estoy creando no es parte de una API pública.
- Si desea utilizar algunos patrones que necesitan combinaciones (por ejemplo, patrón de rasgos apilables ), entonces es una decisión fácil.
- Si tiene dependencias circulares, los mixins con tipos propios pueden ayudar. (Trato de evitar esta situación, pero no siempre es fácil)
- Si desea algunas decisiones dinámicas en tiempo de ejecución sobre cómo hacer la composición, luego la composición del objeto.
En muchos casos, los mixins parecen ser más fáciles (y / o menos detallados), pero estoy bastante seguro de que también tienen algunos inconvenientes, como la "clase de Dios" y otros descritos en dos artículos de Artima: parte 1 , parte 2 (por cierto Me parece que la mayoría de los otros problemas no son relevantes / no son tan graves para scala).
¿Tienes más pistas como estas?
fuente
this => Logging
? No se compila.Otras diferencias que no has mencionado:
( Programación de Scala )
[Martin2003]: Robert C. Martin, Desarrollo de software ágil: principios, patrones y prácticas, Prentice-Hall, 2003
trait
) no tiene parámetros de constructor.De ahí el consejo, todavía de Programming Scala :
Esa última parte, con respecto al estado inicial de un objeto, a menudo ha ayudado a decidir entre clase (y composición de clase) y rasgo (y mixins) para un concepto dado.
fuente
trait
) no tienen parámetros de constructor " . Curiosamente, Dotty (que se convertirá en Scala 3) admite parámetros de rasgos . Como resultado, la regla general de Programming Scala que mencionaste podría evolucionar.