Je suis conscient que c'est une question très basique, mais un intervieweur m'a posé une question très astucieuse et j'étais impuissant :(
Je ne connais que la définition matérielle ou théorique d'une interface et je l'ai également implémentée dans de nombreux projets sur lesquels j'ai travaillé. Mais je ne comprends vraiment pas pourquoi et comment est-ce utile.
Je ne comprends pas non plus une chose dans l'interface. c'est à dire par exemple, nous utilisons
conn.Dispose();
dans enfin bloc. Mais je ne vois pas que cette classe implémente ou hérite de la classe IDisposable
interface ( SqlConnection
) que je veux dire. Je me demande comment je peux simplement appeler le nom de la méthode. Dans le même ordre d'idées, je ne comprends pas comment la méthode Dispose fonctionne car nous devons implémenter le corps de la fonction avec notre propre implémentation pour toutes les méthodes d'interface. Alors, comment les interfaces sont-elles acceptées ou nommées comme contrats? Ces questions ont continué à rouler dans mon esprit jusqu'à présent et, franchement, je n'ai jamais vu de fil conducteur qui expliquerait mes questions d'une manière que je puisse comprendre.
MSDN, comme d'habitude, semble très effrayant et aucune ligne n'est claire là-bas ( Mes amis, veuillez excuser qui sont dans le développement de haut niveau, je pense fermement que tout code ou article devrait atteindre l'esprit de quiconque le voit, donc comme beaucoup d'autres le disent, MSDN n'est pas utile ).
L'intervieweur a déclaré:
Il a 5 méthodes et il est heureux de l'implémenter directement dans la classe, mais si vous devez opter pour une classe ou une interface abstraite, laquelle choisissez-vous et pourquoi? Je lui ai répondu à tous les trucs que j'ai lus dans divers blogs en disant l'avantage et le désavantage de la classe abstraite et de l'interface, mais il n'est pas convaincu, il essaie de comprendre "Pourquoi l'interface" en général. "Pourquoi une classe abstraite" en général même si je ne peux implémenter les mêmes méthodes qu'une seule fois et ne pas la changer.
Je ne vois nulle part sur le net, je pourrais obtenir un article qui m'expliquerait clairement sur les interfaces et son fonctionnement. Je fais partie de ces nombreux programmeurs, qui ne connaissent toujours pas les interfaces (je connais la théorie et les méthodes que j'ai utilisées) mais qui ne sont pas convaincus de l'avoir bien compris.
SqlConnection
hérite deSystem.ComponentModel.Component
qui implémenteIDisposable
.SqlConnection
implémenteIDisposable
.Réponses:
Les interfaces sont excellentes lorsque vous souhaitez créer quelque chose comme ça:
Dans mon exemple, je pourrais être un développeur qui écrit
MyLogClass
, et les autres développeurs, pourraient créer leurs classes, et quand ils voulaient se connecter, ils implémentaient l'interfaceIMyLogInterface
. C'est comme ils me demandaient ce qu'ils devaient implémenter pour utiliser laWriteLog()
méthodeMyLogClass
. La réponse qu'ils trouveront dans l'interface.la source
MyClass
etMyOtherClass
pourquoi n'appeleriez-vous pas simplementaClass.WriteLog()
pourquoi ajouter cette étape supplémentaire. L'implémentation deWriteLog()
resterait différente pour chacune des classes mais vous avez déjà l'objet alors pourquoi le passer à une classe de gestionnaire?MyLogClass
WriteLog
méthode. Ainsi sa méthode peut gérer n'importe quel objet implémentantIMyLogInterface
. Voici un autre article intéressant.Une des raisons pour lesquelles j'utilise des interfaces est que cela augmente la flexibilité du code. Disons que nous avons une méthode qui prend un objet de type de classe Account comme paramètre, tel que:
Le problème avec cela, c'est que le paramètre de méthode est fixé vers une implémentation d'un compte. C'est bien si vous n'avez jamais besoin d'un autre type de compte. Prenons cet exemple, qui utilise à la place une interface de compte comme paramètre.
Cette solution n'est pas figée vers une implémentation, ce qui signifie que je peux lui passer un SuperSavingsAccount ou un ExclusiveAccount (tous deux implémentant l'interface IAccount) et obtenir un comportement différent pour chaque compte implémenté.
la source
Les interfaces sont des contrats que les exécutants doivent suivre. Les classes abstraites permettent des contrats plus des implémentations partagées - ce que les interfaces ne peuvent pas avoir. Les classes peuvent implémenter et hériter de plusieurs interfaces. Les classes ne peuvent étendre qu'une seule classe abstraite.
Pourquoi Interface
IDbCommand
aSqlCommand
etOracleCommand
qui implémentent l'interface de manière spécifique )Pourquoi abstrait
la source
DataContracts
) dans un assembly .NET ( par exemple, Contracts.Shared.dll ) afin que les clients clients .NET puissent facilement interagir en utilisantChannelFactory
(en évitant de générer du code via Ajouter une référence de service, etc. ) ou en utilisant Ajouter une référence de service avec des types partagésDonc, 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 savoir quoi que ce soit d'autre les uns sur les autres.
la source
En un mot - à cause du polymorphisme !
Si vous «programmez sur une interface, pas sur une implémentation», vous pouvez injecter différents objets qui partagent la même interface (type) dans la méthode en tant qu'argument. De cette façon, le code de votre méthode n'est couplé à aucune implémentation d'une autre classe, ce qui signifie qu'il est toujours prêt à fonctionner avec des objets nouvellement créés de la même interface. (Principe d'ouverture / fermeture)
la source
C # n'a pas de typage canard - ce n'est pas parce que vous savez qu'une certaine méthode est implémentée dans un ensemble de classes concrètes que vous pouvez les traiter de la même manière en ce qui concerne l'appel de cette méthode. L'implémentation d'une interface vous permet de traiter toutes les classes qui l'implémentent comme le même type de chose, en ce qui concerne ce que définit cette interface.
la source
Je crois que beaucoup de sang a déjà été versé en posant ces questions, et beaucoup essaient de résoudre ces problèmes en expliquant des termes de type robot qu'aucun humain normal ne peut comprendre.
Alors d'abord. pour savoir pourquoi interface et pourquoi abstrait, vous devez savoir à quoi ils servent. J'ai personnellement appris ces deux en appliquant Factory Class. vous trouvez un bon tuturial sur ce lien
Maintenant, explorons le lien que j'ai déjà donné.
Vous avez une classe de véhicule qui peut changer selon les besoins de l'utilisateur (comme l'ajout d'un camion , d'un réservoir , d'un avion , etc.
et
et les deux ont le contrat IChoice qui dit simplement que ma classe devrait avoir la méthode d'achat
Maintenant, vous voyez, cette interface applique uniquement la méthode
Buy()
mais laisse la classe héritée décider quoi faire lorsqu'elle l'implémente. C'est la limitation d'Interface, en utilisant purement interface, vous pourriez finir par répéter une tâche que nous pouvons implémenter automatiquement en utilisant abstact. Sur notre exemple, disons, l'achat de chaque véhicule a une réduction.Maintenant, en utilisant la classe d'usine, vous pouvez réaliser la même chose, mais en utilisant abstract, vous laissez la classe de base exécuter la
Buy()
méthode.la source
Avec une interface, vous pouvez effectuer les opérations suivantes:
1) Créez des interfaces séparées qui offrent différentes coupes de votre implémentation, permettant une interface plus cohérente.
2) Autorisez plusieurs méthodes avec le même nom entre les interfaces, car bon, vous n'avez aucune implémentation conflictuelle, juste une signature.
3) Vous pouvez effectuer des versions et supprimer votre interface indépendamment de votre implémentation, en vous assurant qu'un contrat est respecté.
4) Votre code peut s'appuyer sur l'abstraction plutôt que sur la concrétion, ce qui permet une injection de dépendances intelligente, y compris l'injection de Mocks de test, etc.
Il y a beaucoup d'autres raisons, j'en suis sûr, ce ne sont que quelques-unes.
Une classe abstraite vous permet d'avoir une base partiellement concrète à partir de laquelle travailler, ce n'est pas la même chose qu'une interface mais a ses propres qualités telles que la possibilité de créer une implémentation partielle en utilisant le modèle de méthode de modèle.
la source
En tant qu'échantillon réel de la réponse @ user2211290:
Les deux
Array
etList
ont une interfaceIList
. Ci-dessous, nous avons unstring[]
et unList<string>
et vérifions les deux avec une méthode en utilisant IList :la source
Vous ne pouvez hériter que d'une seule classe abstraite. Vous pouvez hériter de plusieurs interfaces. Cela détermine ce que j'utilise dans la plupart des cas.
L'avantage de la classe abstraite serait que vous pouvez avoir une implémentation de base. Cependant, dans le cas de IDisposable, une implémentation par défaut est inutile, car la classe de base ne sait pas comment nettoyer correctement les choses. Ainsi, une interface serait plus adaptée.
la source
La classe abstraite et l'interface sont des contrats.
L'idée d'un contrat est que vous spécifiez un comportement. Si vous dites que vous avez mis en œuvre, vous avez accepté le contrat.
Le choix de l'abstrait sur l'interface est.
Tout descendant non abstrait de la classe abstraite implémentera le contrat.
contre
Toute classe qui implémente l'interface implémentera le contrat.
Vous utilisez donc abstract lorsque vous souhaitez spécifier un comportement que tous les descendants doivent implémenter et vous évitez de définir une interface distincte, mais maintenant tout ce qui répond à ce contrat effectivement agrégé doit être un descendant.
la source
Les interfaces consistent à faire une abstraction (un archétype) de l'abstraction (les classes) de la réalité (les objets).
Les interfaces doivent spécifier les termes du contrat sans fournir l'implémentation fournie par les classes.
Les interfaces sont des spécifications:
Les interfaces sont des artefacts de conception pour spécifier le comportement immobile du concept car il est seul et statique.
Les classes sont des artefacts de temps de mise en œuvre pour spécifier la structure mobile de la réalité lorsqu'elle interagit et se déplace.
Qu'est-ce qu'une interface?
Lorsque vous observez un chat, vous pouvez dire que c'est un animal qui a quatre pattes, une tête, un tronc, une queue et des cheveux. Vous pouvez voir qu'il peut marcher, courir, manger et miauler. Etc.
Vous venez de définir une interface avec ses propriétés et ses opérations. En tant que tel, vous n'avez défini aucun modus operandi, mais uniquement des fonctionnalités et des capacités sans savoir comment les choses fonctionnent: vous avez défini des capacités et des distinctions.
En tant que tel, ce n'est pas encore vraiment une classe même si dans UML nous l'appelons une classe dans un diagramme de classes parce que nous pouvons définir des membres privés et protégés pour commencer à avoir une vue approfondie de l'artefact. Ne soyez pas confondu ici car en UML une interface est une chose légèrement différente d'une interface en C #: c'est comme un point d'accès partiel à l'atome d'abstraction. En tant que tel, nous avons dit qu'une classe peut implémenter plusieurs interfaces. En tant que tel, c'est la même chose, mais pas, car les interfaces en C # sont à la fois utilisées pour abstraire l'abstraction et pour limiter cette abstraction en tant que point d'accès. Ce sont deux utilisations différentes. Ainsi, une classe en UML représente une interface de couplage complète à une classe de programmation, alors qu'une interface UML représente une interface de découplage d'une section d'une classe de programmation. En effet, le diagramme de classes en UML ne prend pas en charge l'implémentation et tous ses artefacts sont au niveau de l'interface de programmation. Alors que nous mappons des classes UML à des classes de programmation, il s'agit d'une transposition d'abstraction abstraite en abstraction concrète. Il y a une subtilité qui explique la dichotomie entre le champ du design et le champ de la programmation. Ainsi, une classe en UML est une classe de programmation du point de vue d'une interface de programmation tout en considérant les choses cachées internes.
Les interfaces permettent également de simuler l'héritage multiple lorsqu'il n'est pas disponible de manière maladroite. Par exemple, la classe cat implémentera l'interface cat qui dérive elle-même de l'interface animal. Cette classe de chat implémentera également ces interfaces: marcher, courir, manger et faire un son. Cela compense l'absence d'héritage multiple au niveau de la classe, mais à chaque fois, vous devez tout réimplémenter et vous ne pouvez pas factoriser la réalité au mieux comme la réalité elle-même le fait.
Pour comprendre que nous pouvons nous référer au codage d'objets Pascal où vous définissez dans une unité l'interface et les sections d'implémentation. Dans l'interface, vous définissez les types et dans l'implémentation vous implémentez le type:
Ici, la section interface correspond à la conception de la classe UML tandis que les types d'interfaces sont donc d'autres choses.
Donc, dans notre métier, nous avons un mot, interface , pour désigner deux choses distinctes mais similaires, et c'est une source de confusion.
Toujours en C # par exemple, les interfaces de programmation permettent de compenser l'absence de vrai polymorphisme générique sur les types ouverts sans vraiment réussir l'objectif car vous avez perdu l'habileté fortement typée.
Après tout, des interfaces sont nécessaires pour permettre à des systèmes incompatibles de communiquer sans se soucier de l'implémentation et de la gestion des objets en mémoire comme introduit avec le modèle d'objet commun (distribué).
Qu'est-ce qu'une classe?
Après avoir défini une réduction de la réalité d'un point de vue externe, vous pouvez ensuite la décrire d'un point de vue intérieur: c'est la classe où vous définissez le traitement des données et la gestion des messages pour permettre à la réalité que vous avez encapsulée de prendre vie et d'interagir grâce aux objets utilisant des instances.
Ainsi en UML vous réalisez une immersion fractale dans les roues de la machinerie et vous décrivez les états, les interactions etc. pour pouvoir implémenter l'abstraction du fragment de la réalité que vous voulez manipuler.
En tant que telle, une classe abstraite est en quelque sorte l'équivalent d'une interface du point de vue du compilateur.
Plus d'information
Protocole (programmation orientée objet)
C # - Interfaces
C # - Classes
la source
Laissez-moi vous parler des grille-pain volants.
Il existe, bien sûr, de nombreuses situations dans lesquelles vous pouvez construire un système logiciel fonctionnel sans déclarer ni implémenter aucune interface: toute conception de logiciel orientée objet peut être réalisée en utilisant uniquement des classes.
Là encore, tout système logiciel peut également être implémenté en langage d'assemblage, ou mieux encore en code machine. La raison pour laquelle nous utilisons des mécanismes d'abstraction est qu'ils ont tendance à rendre les choses plus faciles. Les interfaces sont un tel mécanisme d'abstraction.
Ainsi, il se trouve qu'il existe certaines conceptions orientées objet non triviales qui sont tellement plus faciles à implémenter si vous utilisez des interfaces, que les interfaces deviennent pratiquement nécessaires dans ces cas.
Ces conceptions non triviales ont à voir avec l'héritage multiple, qui, dans sa «vraie» forme, se produit lorsqu'une classe hérite non pas d'une seule classe de base, mais de deux classes de base ou plus. Cette vraie forme n'est pas possible en C #, mais avant que des langages comme C # et Java n'entrent en vigueur, le langage qui régnait était le C ++, qui prend entièrement en charge le véritable héritage multiple. Malheureusement, le véritable héritage multiple s'est avéré ne pas être une très bonne idée, car il complique énormément la conception du langage, et il donne également lieu à divers problèmes, par exemple le fameux "Diamond Problem". (Voir "Quel est le problème exact de l'héritage multiple?" Réponse de J Francis )
Donc, si quelqu'un voulait construire une classe «grille-pain volant», il hériterait d'une classe «grille-pain» existante et aussi d'une classe «grille-pain» existante. Le type de problème auquel ils étaient susceptibles de se heurter était que l'alimentation de la classe grille-pain était probablement une prise murale, tandis que l'alimentation de la classe des machines volantes était susceptible d'être de la nourriture pour pigeons, et la nouvelle classe résultante serait soit en quelque sorte avoir les deux, ou on ne sait pas lequel il aurait. (Le problème du diamant.)
Les créateurs de langages comme C # et Java ont décidé de ne pas autoriser un véritable héritage multiple, afin de garder le langage simple et d'éviter les pièges comme le Diamond Problem. Cependant, une certaine forme d'héritage multiple est toujours nécessaire (ou du moins très souhaitable), donc dans ces langages, ils ont introduit des interfaces comme un moyen de prendre en charge une forme moindre d'héritage multiple tout en évitant les problèmes et la complexité d'un véritable héritage multiple.
Dans cette forme moindre d'héritage multiple, vous n'êtes pas autorisé à avoir une classe qui hérite de plusieurs classes de base, mais vous pouvez au moins hériter d'une ou plusieurs interfaces. Donc, si vous voulez construire un grille-pain volant, vous ne pouvez pas hériter à la fois d'une classe de grille-pain existante et d'une classe de vol existante, mais ce que vous pouvez faire est d'hériter d'une classe de grille-pain existante, puis d'exposer une interface volante que vous implémentez vous-même, éventuellement en utilisant tout moyen dont vous avez déjà hérité du grille-pain.
Ainsi, à moins que vous ne ressentiez le besoin de créer une classe qui regroupe deux ensembles de fonctionnalités différents et non liés, vous n'aurez besoin d'aucune forme d'héritage multiple, vous n'aurez donc pas besoin de déclarer ou d'implémenter des interfaces.
la source
Les interfaces permettent au concepteur de classe de rendre les méthodes disponibles très claires pour l'utilisateur final. Ils font également partie intégrante du polymorphisme.
la source
Je ne publierai pas la définition d'une interface par rapport à une classe abstraite car je pense que vous connaissez très bien la théorie et je suppose que vous connaissez les principes SOLID, alors soyons pratiques.
Comme vous le savez, les interfaces ne peuvent pas avoir de code, donc les inconvénients sont assez simples à comprendre.
si vous avez besoin d'initialiser la propriété de votre classe en fournissant un constructeur ou si vous souhaitez fournir une partie de l'implémentation, une classe abstraite conviendrait parfaitement à une interface qui ne vous permettrait pas de le faire.
Donc, en général, vous devriez préférer la classe abstraite aux interfaces lorsque vous devez fournir un constructeur ou tout code au client qui héritera / étendra votre classe
la source
Les classes abstraites sont créées pour les entités liées alors que les interfaces peuvent être utilisées pour les entités non liées.
Par exemple, si j'ai deux entités dites Animal et Humain, alors je vais opter pour Interface où, comme si je devais aller en détail, dire Tigre, lion et vouloir être en relation avec Animal, alors je choisirai la classe Animal Abstract.
ressemblera à ci-dessous
la source