J'étudie et je code en C # depuis quelque temps maintenant. Mais encore, je ne peux pas comprendre l'utilité des interfaces. Ils apportent trop peu à la table. À part fournir les signatures de fonction, ils ne font rien. Si je me souviens des noms et de la signature des fonctions à implémenter, ils ne sont pas nécessaires. Ils ne sont là que pour s’assurer que lesdites fonctions (dans l’interface) sont implémentées dans la classe qui en hérite.
C # est un excellent langage, mais il vous donne parfois l’impression que Microsoft crée d’abord le problème (ne permet pas l’héritage multiple), puis fournit la solution, ce qui est plutôt fastidieux.
C'est ce que je comprends, basé sur une expérience de codage limité. Quelle est votre vision des interfaces? À quelle fréquence les utilisez-vous et qu'est-ce qui vous fait le faire?
la source
Réponses:
Correct. C'est un avantage suffisamment impressionnant pour justifier la fonctionnalité. Comme d'autres l'ont dit, une interface est une obligation contractuelle d'implémenter certaines méthodes, propriétés et événements. L'avantage incontestable d'un langage à typage statique est que le compilateur peut vérifier qu'un contrat sur lequel votre code s'appuie est réellement respecté.
Cela dit, les interfaces sont un moyen assez faible de représenter les obligations contractuelles. Si vous souhaitez une manière plus forte et plus flexible de représenter les obligations contractuelles, reportez-vous à la fonctionnalité Contrats de code fournie avec la dernière version de Visual Studio.
Et bien je suis content que ça te plaise.
Toutes les conceptions logicielles complexes résultent de la mise en balance de caractéristiques contradictoires et de la recherche du «point idéal» offrant des avantages considérables pour des coûts minimes. Nous avons appris de douloureuses expériences que les langages autorisant l'héritage multiple aux fins du partage de la mise en œuvre ont des avantages relativement modestes et des coûts relativement élevés. Autoriser l'héritage multiple uniquement sur les interfaces, qui ne partagent pas les détails de la mise en œuvre, offre de nombreux avantages de l'héritage multiple sans la plupart des coûts.
la source
Assume
appels, pour des cas comme des membres de tableau ou d'énumération. Après avoir tout ajouté et vu le gâchis statiquement vérifié que j'avais, je suis revenu en contrôle de source car cela réduisait la qualité de mon projet.Donc, dans cet exemple, le PowerSocket ne sait rien d’autre sur les autres objets. Les objets dépendent tous de la puissance fournie par le PowerSocket. Ils implémentent donc IPowerPlug et peuvent ainsi s'y connecter.
Les interfaces sont utiles car elles fournissent des contrats que les objets peuvent utiliser pour travailler ensemble sans avoir besoin de rien savoir les uns des autres.
la source
Le but des interfaces n'est pas de vous aider à vous rappeler quelle méthode à implémenter, c'est ici pour définir un contrat . Dans l' exemple de foreach P.Brian.Mackey (ce qui s'avère être faux , mais on s'en fiche), IEnumerable définit un contrat entre foreach et toute autre chose énumérable. Il dit: "Qui que vous soyez, tant que vous respectez le contrat (implémentez IEnumerable), je vous promets que je vais parcourir tous vos éléments". Et c'est excellent (pour un langage non dynamique).
Grâce aux interfaces, vous pouvez obtenir un couplage très faible entre deux classes.
la source
Les interfaces sont le meilleur moyen de conserver des constructions bien découplées.
Lorsque vous écrivez des tests, vous constaterez que des classes concrètes ne fonctionneront pas dans votre environnement de test.
Exemple: vous souhaitez tester une classe qui dépend d'une classe de service d'accès aux données . Si cette classe parle à un service Web ou à une base de données, votre test unitaire ne s'exécutera pas dans votre environnement de test (il est également devenu un test d'intégration).
Solution? Utilisez une interface pour votre service d'accès aux données et simulez cette interface afin de pouvoir tester votre classe en tant qu'unité.
D'autre part, WPF & Silverlight ne jouent pas du tout avec les interfaces en matière de reliure. C'est une jolie vilaine ride.
la source
Les interfaces sont l'épine dorsale du polymorphisme (statique)! L'interface est ce qui compte. L'héritage ne fonctionnerait pas sans interfaces, car les sous-classes héritent essentiellement de l'interface déjà implémentée du parent.
Assez souvent. Tout ce qui doit être connectable est une interface dans mes applications. Souvent, vous avez des classes par ailleurs non liées qui doivent fournir le même comportement. Vous ne pouvez pas résoudre de tels problèmes avec l'héritage.
Besoin de différents algorithmes pour effectuer des opérations sur les mêmes données? Utilisez une interface ( voir modèle de stratégie )!
Voulez-vous utiliser différentes implémentations de liste? Code contre une interface et l'appelant n'a pas besoin de s'inquiéter de la mise en œuvre!
Il a été considéré comme une bonne pratique (pas seulement en POO) de coder des interfaces depuis des siècles, pour une raison unique: il est facile de modifier une implémentation lorsque vous réalisez qu'elle ne correspond pas à vos besoins. C’est assez fastidieux d’essayer d’atteindre cet objectif uniquement avec un héritage multiple ou de créer des classes vides afin de fournir l’interface nécessaire.
la source
Vous avez probablement utilisé
foreach
et trouvé cet outil d'itération très utile. Saviez-vous qu'il faut une interface pour fonctionner, IEnumerable ?C'est certainement un cas concret qui parle de l'utilité d'une interface.
la source
Les interfaces servent à coder les objets, tout comme une fiche au câblage domestique. Souhaitez-vous souder votre radio directement au câblage de votre maison? Que diriez-vous de votre aspirateur? Bien sûr que non. La fiche et la prise de courant dans laquelle elle s’insère constituent l’interface entre le câblage de votre domicile et le périphérique qui en a besoin. Le câblage de votre domicile n'a pas besoin de connaître le périphérique, à part qu'il utilise une fiche à trois broches mise à la terre et qu'il nécessite une alimentation électrique à 120VAC <= 15A. Inversement, le périphérique ne nécessite aucune connaissance compliquée de la connexion de votre maison. Il comporte en outre une ou plusieurs prises à trois broches idéalement placées qui fournissent 120 VCA <= 15A.
Les interfaces remplissent une fonction très similaire dans le code. Un objet peut déclarer qu'une variable, un paramètre ou un type de retour particulier est d'un type d'interface. L'interface ne peut pas être instanciée directement avec un
new
mot clé, mais mon objet peut être donné, ou trouver, la mise en oeuvre de cette interface avec laquelle il devra travailler. Une fois que l'objet a sa dépendance, il n'a pas besoin de savoir exactement quelle est cette dépendance, il doit juste savoir qu'il peut appeler les méthodes X, Y et Z sur la dépendance. Les implémentations de l'interface n'ont pas besoin de savoir comment elles seront utilisées, elles doivent juste savoir qu'elles devront fournir les méthodes X, Y et Z avec des signatures particulières.Ainsi, en résumant plusieurs objets derrière la même interface, vous fournissez un ensemble commun de fonctionnalités à tout consommateur d’objets de cette interface. Vous n'êtes pas obligé de savoir que l'objet est, par exemple, une liste, un dictionnaire, une liste LinkedList, une liste OrderedList ou autre. Comme vous savez que tous ces éléments sont IEnumerables, vous pouvez utiliser les méthodes de IEnumerable pour parcourir chaque élément de ces collections, un à la fois. Vous n'avez pas besoin de savoir qu'une classe de sortie est un ConsoleWriter, un FileWriter, un NetworkStreamWriter ou même un MulticastWriter prenant d'autres types d'écrivains; tout ce que vous devez savoir, c'est qu'ils sont tous des IWriters (ou autre), et ils ont donc une méthode "Write" dans laquelle vous pouvez passer une chaîne, et cette chaîne sera sortie.
la source
Bien qu'il soit clair que le programmeur (au moins tout d'abord) a un héritage multiple, il s'agit d'une omission presque triviale et vous ne devriez (dans la plupart des cas) pas compter sur l'héritage multiple. Les raisons de ceci sont complexes, mais si vous voulez vraiment en apprendre plus, considérez l'expérience des deux langages de programmation les plus célèbres (par TIOBE index ) qui le supportent: C ++ et Python (respectivement 3ème et 8ème).
En Python, l'héritage multiple est pris en charge, mais il est presque universellement mal compris par les programmeurs. Pour vous dire que vous savez comment ça marche, entend lire et comprendre ce document sur le sujet: Ordre de résolution de méthode . Une autre chose qui se passe en Python, c'est que les interfaces sont en quelque sorte entrées dans le langage - Zope.Interfaces.
Pour C ++, recherchez "la hiérarchie du diamant C ++" dans Google et voyez la laideur qui est sur le point de vous couvrir. Les professionnels de C ++ savent utiliser l'héritage multiple. Tous les autres jouent généralement sans savoir quels seront les résultats. Une autre chose qui montre à quel point les interfaces sont utiles est le fait que, dans de nombreux cas, une classe peut avoir besoin de redéfinir complètement le comportement de son parent. Dans de tels cas, l'implémentation parent est inutile et n'impose à la classe enfant que de la mémoire pour les variables privées du parent, ce qui n'a peut-être pas d'importance dans l'âge C #, mais qui importe lorsque vous effectuez une programmation intégrée. Si vous utilisez une interface, ce problème est inexistant.
En conclusion, les interfaces sont, à mon avis, un élément essentiel de la programmation orientée objet, car elles font respecter un contrat. L'héritage multiple est utile dans des cas limités, et en général uniquement pour les gars qui savent l'utiliser. Donc, si vous êtes débutant, vous êtes celui qui est traité par le manque d'héritage multiple - cela vous donne une meilleure chance de ne pas vous tromper .
De plus, historiquement, l'idée d'une interface est ancrée bien avant les spécifications de conception C # de Microsoft. La plupart des gens considèrent que C # est une mise à niveau par rapport à Java (au sens le plus large du terme) et devinent d'où vient que C # tire ses interfaces - Java. Protocole est un ancien mot pour le même concept, et il est bien plus ancien que .NET.
Mise à jour: Je vois maintenant que j'aurais peut-être répondu à une question différente - Pourquoi les interfaces plutôt que l'héritage multiple, mais cela semblait être la réponse que vous cherchiez. En outre, une langue OO devrait avoir au moins une des deux et les autres réponses ont couvert votre question initiale.
la source
Il m'est difficile d'imaginer un code C # propre et orienté objet sans utiliser d'interfaces. Vous les utilisez chaque fois que vous souhaitez imposer la disponibilité de certaines fonctionnalités sans forcer les classes à hériter d'une classe de base spécifique, ce qui permet à votre code d'avoir le niveau de couplage (faible) approprié.
Je ne suis pas d'accord pour dire que l'héritage multiple est mieux que d'avoir des interfaces, même avant de commencer à argumenter que l'héritage multiple vient avec son propre ensemble de problèmes. Les interfaces sont un outil de base pour permettre le polymorphisme et la réutilisation du code, de quoi a-t-il besoin de plus?
la source
Personnellement, j'adore la classe abstraite et l'utilise plus qu'une interface. La principale différence vient de l'intégration avec des interfaces .NET telles que IDisposable, IEnumerable, etc., et COM interop. De plus, l'interface demande un peu moins d'effort en écriture qu'une classe abstraite et une classe peut implémenter plusieurs interfaces alors qu'elle ne peut hériter que d'une classe.
Cela dit, je trouve que la plupart des choses pour lesquelles je voudrais utiliser une interface sont mieux servies par une classe abstraite. Les fonctions virtuelles pures - fonctions abstraites - vous permettent de forcer un implémenteur à définir une fonction similaire à la manière dont une interface force un implémenteur à définir tous ses membres.
Toutefois, vous utilisez généralement une interface lorsque vous ne souhaitez pas imposer une conception donnée à la super-classe, alors que vous utiliseriez une classe abstraite pour obtenir une conception réutilisable déjà largement implémentée.
J'ai beaucoup utilisé les interfaces avec l'écriture d'environnements de plug-in utilisant l'espace de noms System.ComponentModel. Ils sont très utiles.
la source
Je peux dire que je rapporte à cela. Quand j'ai commencé à apprendre sur OO et C #, moi aussi, je n'ai pas eu d'interfaces. C'est bon. Nous devons juste trouver quelque chose qui vous fera apprécier le confort des interfaces.
Laissez-moi essayer deux approches. Et pardonnez-moi pour les généralisations.
Essayer 1
Dites que vous êtes un anglophone. Vous allez dans un autre pays où l'anglais n'est pas la langue maternelle. Vous avez besoin d'aide. Vous avez besoin de quelqu'un qui peut vous aider.
Demandez-vous: "Hey, êtes-vous né aux États-Unis?" C'est l'héritage.
Ou demandez-vous: "Hey, parlez-vous anglais"? Ceci est l'interface.
Si vous vous souciez de ce qu'il fait, vous pouvez compter sur des interfaces. Si vous vous souciez de ce qui est, vous comptez sur l'héritage.
C'est correct de compter sur l'héritage. Si vous avez besoin de quelqu'un qui parle anglais, qui aime le thé et le football, vous feriez mieux de demander un Britannique. :)
Essayez 2
Ok, essayons un autre exemple.
Vous utilisez différentes bases de données et vous devez implémenter des classes abstraites pour les utiliser. Vous passerez votre classe à une classe du fournisseur de base de données.
L'héritage multiple, vous dites? Essayez cela avec le cas ci-dessus. Tu ne peux pas. Le compilateur ne saura pas quelle méthode Connect vous essayez d'appeler.
Nous pouvons maintenant travailler, du moins en C #, avec lequel nous pouvons implémenter des interfaces de manière explicite.
Conclusion
Les exemples ne sont pas les meilleurs, mais je pense que ça donne raison.
Vous n'obtiendrez que des interfaces lorsque vous en ressentez le besoin. Jusqu'à ce que vous pensiez qu'ils ne sont pas pour vous.
la source
Il y a 2 raisons principales:
la source
L'utilisation d'interfaces aide un système à rester découplé et donc plus facile à refactoriser, à modifier et à redéployer. C’est un concept fondamental pour l’orthodoxie orientée objet et j’en ai été informé lorsque des gourous du C ++ ont créé des "classes abstraites pures" qui sont tout à fait équivalentes aux interfaces.
la source
Les interfaces en elles-mêmes ne sont pas très utiles. Mais une fois implémenté par des classes concrètes, vous voyez que cela vous donne la possibilité d’avoir une ou plusieurs implémentations. L'avantage est que les objets utilisant l'interface n'ont pas besoin de savoir comment vont les détails de l'implémentation réelle - cela s'appelle l'encapsulation.
la source
Ils sont principalement utilisés pour la réutilisation du code. Si vous codez sur l'interface, vous pouvez utiliser une classe différente qui hérite de cette interface et ne pas tout casser.
En outre, ils sont très utiles dans les services Web où vous voulez que le client sache ce qu’une classe fait (pour qu’elle puisse la consommer), mais ne leur donnez pas le code réel.
la source
En tant que jeune programmeur / développeur, rien qu'en apprenant le C #, vous ne verrez peut-être pas l'utilité d'une interface, car vous pourriez écrire vos codes à l'aide de vos classes et le code fonctionne bien, mais dans le scénario réel, la création d'une application évolutive, robuste et maintenable implique l'utilisation de certaines architectures et modèles, qui ne peuvent être rendus possibles qu’en utilisant l’interface, par exemple en injection de dépendance.
la source
Une implémentation du monde réel:
Vous pouvez convertir un objet en tant que type d'interface:
Vous pouvez créer une liste d'une interface
Avec ces objets, vous pouvez accéder à n’importe quelle méthode ou propriété d’interface. De cette manière, vous pouvez définir une interface pour votre partie d'un programme. Et construisez la logique autour de cela. Ensuite, quelqu'un d'autre peut implémenter votre interface dans leurs objets Business. Si les BO changent, ils peuvent changer la logique des composants d'interface sans exiger de modification de la logique de votre pièce.
la source
Les interfaces permettent une modularité de type plugin en fournissant un mécanisme permettant aux classes de comprendre (et de s’abonner à) certains types de messages fournis par votre système. Je vais élaborer.
Dans votre application, vous décidez que chaque fois qu'un formulaire est chargé ou rechargé, vous souhaitez que tous les éléments qu'il héberge soient effacés. Vous définissez une
IClear
interface qui implémenteClear
. En outre, vous décidez que chaque fois que l'utilisateur appuie sur le bouton d'enregistrement, le formulaire doit tenter de conserver son état. Ainsi, tout ce qui resteISave
reçoit un message pour persister son état. Bien entendu, sur le plan pratique, la plupart des interfaces traitent plusieurs messages.Ce qui distingue les interfaces, c'est qu'un comportement commun peut être obtenu sans héritage. La classe qui implémente une interface donnée comprend simplement comment se comporter lorsqu'une commande est émise (un message de commande) ou comment répondre à une requête (un message d'interrogation). Essentiellement, les classes de votre application comprennent les messages fournis par votre application. Cela facilite la construction d'un système modulaire dans lequel les choses peuvent être branchées.
Dans la plupart des langages, il existe des mécanismes (tels que LINQ ) pour interroger des éléments liés à une interface. Cela vous aidera généralement à éliminer la logique conditionnelle, car vous n'aurez pas à dire à des choses différentes (qui ne sont pas nécessairement dérivées de la même chaîne d'héritage) comment se comporter de manière similaire (selon un message particulier). Au lieu de cela, vous rassemblez tout ce qui comprend un certain message (respecte une interface) et publiez le message.
Par exemple, vous pourriez remplacer ...
...avec:
Ce qui ressemble effectivement beaucoup à:
De cette façon, nous pouvons éviter par programmation de demander à chaque chose de se vider d'elle-même. Et lorsque des éléments dissociables sont ajoutés à l'avenir, ils répondent simplement sans code supplémentaire.
la source
Le pseudocode est le suivant:
Les dernières classes peuvent être des implémentations complètement différentes.
À moins que l'héritage multiple ne soit possible, l'héritage impose l'implémentation de la classe parente rendant les choses plus rigides. En revanche, la programmation par rapport aux interfaces peut permettre à votre code ou à un framework d’être extrêmement flexible. Si vous rencontrez un jour un cas où vous souhaitiez pouvoir échanger des classes dans une chaîne d'héritage, vous comprendrez pourquoi.
Par exemple, un framework qui fournit à l’origine un lecteur destiné à lire des données à partir d’un disque pourrait être ré-implémenté pour faire quelque chose de la même nature mais d’une manière totalement différente. Comme interpréter le code Morse par exemple.
la source