Au cours d'une de mes études sur les subtilités de C #, je suis tombé sur un passage intéressant concernant l'implémentation d'interface explicite.
While this syntax is quite helpful when you need to resolve name clashes,
you can use explicit interface implementation simply to hide more "advanced"
members from the object level.
La différence entre autoriser l'utilisation object.method()
ou exiger le moulage ((Interface)object).method()
semble être une obscénité mesquine à mes yeux inexpérimentés. Le texte a noté que ce cachera la méthode de IntelliSense au niveau de l' objet, mais pourquoi voulez - vous voulez faire que s'il n'a pas été nécessaire pour éviter les conflits de nom?
c#
design
interfaces
Nathanus
la source
la source
Réponses:
Imaginez une situation où une interface force une classe à implémenter des méthodes qui n'ont pas vraiment de sens dans le cadre de la classe. Cela peut souvent se produire lorsque les interfaces sont particulièrement grandes et violent le principe de ségrégation des interfaces.
Cette classe doit implémenter l'interface, mais au lieu de polluer son interface publique très visible avec des méthodes qui n'ont pas de sens, vous pouvez implémenter explicitement les méthodes que vous ne voulez pas être évidemment disponibles. L'interface publique très visible de la classe est la façon dont vous souhaitez que la classe soit utilisée, et l'implémentation explicite est là lorsque la classe est accessible via l'interface.
la source
IEnumerable<T>
qui se comporte comme la concaténation de deux autres. Si elleIEnumerable<T>
comprenait une propriété pour dire si son nombre était connu, potentiellement infini, ou aucun des deux, ainsi qu'une méthode pour demander quel était son nombre, une classe qui agrégerait plusieursIEnumerable<T>
et se comporterait comme une concaténation pourrait signaler efficacement son nombre dans le cas où certains de les collections encapsulées connaissaient leurs comptes.L'application la plus utile que j'ai trouvée concerne l'implémentation d'usines. Dans de nombreux cas, il est utile de créer des classes qui sont modifiables à l'intérieur de l'usine mais immuables aux classes externes. Cela peut être facilement implémenté en Java en utilisant des classes internes, en rendant les champs et leurs setters privés et en exposant uniquement les getters en tant que membres publics. Cependant en C #, j'ai dû utiliser des interfaces explicites pour réaliser la même chose. J'expliquerai plus loin:
En Java, la classe interne ET la classe externe peuvent accéder aux membres privés les unes des autres, ce qui est tout à fait logique car les classes sont très étroitement liées. Ils sont dans le même fichier de code et sont probablement développés par le même développeur. Cela signifie que les champs et méthodes privés de la classe interne sont toujours accessibles par la fabrique pour modifier leurs valeurs. Mais les classes externes ne pourront pas accéder à ces champs sauf via leurs getters publics.
Cependant, en C #, les classes externes ne peuvent pas accéder aux membres privés des classes internes, ce concept n'est donc pas directement applicable. J'ai utilisé une interface explicite comme solution de contournement en définissant une interface privée dans la classe externe et en l'implémentant explicitement dans la classe interne. De cette façon, seule la classe externe peut accéder aux méthodes de cette interface de la même manière que cela se fait en Java (mais elles doivent être des méthodes, pas des champs).
Exemple:
C'est pour cela que j'utiliserais des interfaces explicites.
la source
Si une classe implémente deux interfaces qui contiennent un membre avec la même signature, l'implémentation de ce membre sur la classe obligera les deux interfaces à utiliser ce membre comme implémentation. Dans l'exemple suivant, tous les appels pour
Paint
appeler la même méthode. C #En revanche, l'implémentation explicite de l'un (ou des deux) d'entre eux vous permet de spécifier un comportement différent pour chacun.
la source
Les interfaces explicites sont pratiques lorsqu'un objet a deux ou plusieurs formes de communication très distinctes.
Par exemple, un objet qui gère une collection d'objets enfants qui doivent communiquer avec le parent.
Il y a certaines actions que nous voulons seulement accessibles aux appelants externes et certaines actions que nous voulons seulement accessibles aux objets enfants.
Des interfaces explicites contribuent à garantir ce fossé.
la source
Peut-être si vous aviez des fonctionnalités utiles aux utilisateurs, mais seulement si vous savez vraiment ce que vous faites (assez pour avoir lu la documentation pour en savoir plus sur la fonction) mais cela risque de casser des choses si vous ne le faites pas.
Pourquoi vous feriez cela plutôt que de fournir, disons une deuxième "interface de fonctionnalités avancées", je ne sais pas.
la source
Le code est généralement lu plus qu'il n'est écrit et j'utilise uniquement Intellisense pour écrire du code rapidement. Je n'écrirais pas de code d'une manière particulière juste pour rendre Intellisense plus agréable.
Je ne vois pas particulièrement comment
(Objet (Interface)) .method () est plus lisible que object.method ().
Si j'avais beaucoup de méthodes sur un objet particulier, je pourrais me demander si c'est un objet divin et devrait en fait être divisé en plusieurs objets plus simples.
la source