De vez en cuando, me encuentro con un caso en el que quiero que una colección de clases posea una lógica similar. Por ejemplo, tal vez yo quiero tanto un Bird
y un Airplane
para poder Fly()
. Si está pensando en un "patrón de estrategia", estaría de acuerdo, pero incluso con la estrategia, a veces es imposible evitar la duplicación del código.C# tiene clases e interfaces abstractas, ¿debería tener también "mixins"?
Por ejemplo, digamos que se aplica lo siguiente (y esto es muy similar a una situación real que encontré hace poco):
- Tanto
Bird
yAirplane
necesitará tener una instancia de un objeto que implementaIFlyBehavior
. - Tanto
Bird
yAirplane
necesidad de pedir la instanciaIFlyBehavior
aFly()
cuandoOnReadyToFly()
se llama. - Tanto
Bird
yAirplane
necesidad de pedir la instanciaIFlyBehavior
aLand()
cuandoOnReadyToLand()
se llama. OnReadyToFly()
yOnReadyToLand()
son privadas.Bird
Animal
heredaPeopleMover
Ahora, digamos que más tarde añadimos Moth
, HotAirBalloon
, y 16 otros objetos, y digamos que todos siguen el mismo patrón.
Ahora vamos a necesitar 20 copias del código siguiente:
private IFlyBehavior _flyBehavior;
private void OnReadyToFly()
{
_flyBehavior.Fly();
}
private void OnReadyToLand()
{
_flyBehavior.Land();
}
Dos cosas que no me gustan de este:
No es muy seco (la las mismas nueve líneas de código se repiten una y otra vez). Si descubrimos un error o añadido un
BankRight()
-IFlyBehavior
, tendríamos que propagar los cambios a todas las 20 clases.No hay ninguna manera de hacer cumplir que los 20 clases implementan esta lógica interna repetitivo consistente. No podemos usar una interfaz porque las interfaces solo permiten miembros públicos. No podemos utilizar una clase base abstracta porque los objetos ya heredan las clases base, y C# no permite la herencia múltiple (e incluso si las clases ya no heredan las clases, que más tarde tal vez desee agregar un nuevo comportamiento que implementa, por ejemplo,
ICrashable
, por lo que una clase base abstracta no siempre será una solución viable).
¿Qué pasa si ...?
¿Qué pasa si C# tenía un nuevo constructo, dicen pattern
o template
o [complete su idea aquí], que funcionó como una interfaz, pero le ha permitido poner modificadores de acceso privados o protegidos en los miembros? Usted todavía necesita para proporcionar una implementación para cada clase, pero si su clase implementa el patrón PFlyable
, tendría al menos tener una manera de hacer cumplir todas las clases que tenía el código repetitivo necesario llamar Fly()
y Land()
.Y, con un IDE moderno como Visual Studio, podría generar automáticamente el código usando el comando "Implementar patrón".
Personalmente, creo que tendría más sentido ampliar el significado de la interfaz para cubrir cualquier contrato, ya sea interno (privado/protegido) o externo (público), pero sugerí agregar una construcción completamente nueva porque la gente parece ser muy inflexible sobre el significado de la palabra "interfaz", y no quería que la semántica se convirtiera en el foco de las respuestas de las personas.
Preguntas:
Independientemente de cómo lo llame, me gustaría saber si la función que estoy sugiriendo aquí tiene sentido. ¿Necesitamos alguna forma de manejar los casos en los que no podemos abstraer tanto código como nos gustaría, debido a la necesidad de modificadores de acceso restrictivos o por razones ajenas al control del programador?
actualización
Desde el comentario de AakashM, creo que ya hay un nombre para la función que estoy solicitando: una Mixin. Entonces, creo que mi pregunta se puede resumir a: "¿Debería C# permitir Mixins?"
Creo que quiere estos: http://en.wikipedia.org/wiki/Mixin – AakashM
@Aakash, creo que tiene razón. Es bueno tener una palabra para lo que estoy describiendo :) – devuxer
@Aakash, si conviertes tu comentario en una respuesta, es muy probable que lo marque :) Tal vez añada su opinión sobre si mixins sería una buena característica para C# para agregar. Gracias. – devuxer