Chaque si souvent, je tombe sur un cas où j'ai envie d'une collection de classes de tous pour posséder la même logique. Par exemple, peut-être que je veux à la fois un Bird
et Airplane
pouvoir Fly()
. Si vous êtes en train de penser "stratégie de modèle", je suis d'accord, mais même avec de la stratégie, il est parfois impossible d'éviter la duplication de code.
Par exemple, disons que les suivants s'appliquent (et ceci est très similaire à une situation réelle j'ai récemment rencontré):
- Les deux
Bird
etAirplane
besoin de tenir une instance d'un objet qui implémenteIFlyBehavior
. - Les deux
Bird
etAirplane
besoin de demander à l'IFlyBehavior
exemple d'Fly()
lorsqueOnReadyToFly()
est appelé. - Les deux
Bird
etAirplane
besoin de demander à l'IFlyBehavior
exemple d'Land()
lorsqueOnReadyToLand()
est appelé. -
OnReadyToFly()
etOnReadyToLand()
sont privées. -
Bird
hériteAnimal
etAirplane
héritePeopleMover
.
Maintenant, disons-nous ajouter ultérieurement Moth
, HotAirBalloon
, et de 16 autres objets, et disons qu'ils suivent tous le même schéma.
Maintenant, nous allons avoir besoin de 20 copies le code suivant:
private IFlyBehavior _flyBehavior;
private void OnReadyToFly()
{
_flyBehavior.Fly();
}
private void OnReadyToLand()
{
_flyBehavior.Land();
}
Deux choses que je n'aime pas à propos de ceci:
Ce n'est pas très SEC (même neuf lignes de code sont répétés maintes et maintes fois). Si nous avons découvert un bug ou d'ajout d'un
BankRight()
deIFlyBehavior
, nous aurions besoin de propager les modifications à tous les 20 classes.Il n'y a pas de toute façon de la faire respecter toutes les 20 classes implémentent cette répétitif logique interne de manière cohérente. Nous ne pouvons pas utiliser une interface parce que les interfaces ne permettent que des membres du public. Nous ne pouvons pas utiliser une classe de base abstraite parce que les objets héritent des classes de base, et C# ne permet pas l'héritage multiple (et même si les classes n'a pas déjà hériter de classes, nous pourrions plus tard souhaitez ajouter un nouveau comportement qui met en œuvre, disons,
ICrashable
, donc une classe de base abstraite n'est pas toujours va être une solution viable).
Que faire si...?
Que faire si C# a une nouvelle construction, dire pattern
ou template
ou [remplir votre idée ici], qui a travaillé comme une interface, mais vous a permis de mettre privés ou protégés des modificateurs d'accès sur les membres? Vous auriez encore besoin de fournir une implémentation pour chaque classe, mais si votre classe de mise en œuvre de l' PFlyable
modèle, vous avez au moins un moyen d'assurer que chaque classe avait le code réutilisable appel Fly()
et Land()
. Et, avec un IDE moderne, tels que Visual Studio, vous seriez en mesure de générer automatiquement le code à l'aide de la "mettre en Œuvre Motif de la commande".
Personnellement, je pense qu'il serait plus judicieux d'étendre le sens de l'interface de la couverture de tout contrat, qu'il soit interne (privé/protégé) ou externe (public), mais je suggère d'ajouter une toute nouvelle construisons d'abord parce que les gens semblent être très catégorique sur le sens du mot "interface", et je ne voulais pas la sémantique de devenir le centre de réponses.
Questions:
Peu importe comment vous l'appelez, je voudrais savoir si la fonctionnalité que je suis en train de suggérer un sens. Avons-nous besoin d'une certaine façon de gérer les cas où nous ne pouvons pas nous soustraire autant de code que nous aimerions, en raison de la nécessité pour restreindre les modificateurs d'accès ou pour des raisons en dehors de l'entreprise de programmation de contrôle?
Mise à jour
De AakashM commentaire, je crois qu'il existe déjà un nom pour la fonctionnalité que je suis en demandant: un Mixin. Donc, je suppose que ma question peut être réduit à: "Doit C# permettent de Mixin?"