Comment saurai-je quand créer une interface?

Je suis à un stade de mon apprentissage en développement où je pense que je dois en apprendre davantage sur les interfaces.

Je lis souvent à leur sujet, mais il semble que je ne puisse pas les saisir.

J’ai lu des exemples comme: Classe de base animale, avec interface IAnimal pour des choses comme «Walk», «Run», «GetLegs», etc. – mais je n’ai jamais travaillé sur quelque chose et je me suis dit ici!”

Qu’est-ce que je rate? Pourquoi est-ce un concept si difficile à saisir pour moi! Je suis juste intimidé par le fait que je ne réalise peut-être jamais un besoin concret – surtout en raison d’un aspect manquant de leur compréhension! J’ai l’impression de manquer quelque chose en termes de développement! Si quelqu’un a vécu une telle expérience et a fait une percée, j’apprécierais quelques conseils sur la façon de comprendre ce concept. Je vous remercie.

il résout ce problème concret:

vous avez a, b, c, d de 4 types différents. partout dans votre code, vous avez quelque chose comme:

a.Process(); b.Process(); c.Process(); d.Process(); 

pourquoi ne pas les implémenter IProcessable, puis faire

 List list; foreach(IProcessable p in list) p.Process(); 

Cela va beaucoup mieux lorsque vous ajoutez, disons, 50 types de classes qui font tous la même chose.


Un autre problème concret:

Avez-vous déjà regardé System.Linq.Enumerable? Il définit une tonne de méthodes d’extension qui fonctionnent sur tout type qui implémente IEnumerable. Parce que tout ce qui implémente IEnumerable dit essentiellement “Je supporte l’itération dans un modèle de type foreach non ordonné”, vous pouvez définir des comportements complexes (Count, Max, Where, Select, etc.) pour tout type énumérable.

J’aime beaucoup la réponse de Jimmy, mais j’ai besoin d’y append quelque chose. La clé de la chose est le “capable” dans IProcessable. Il indique une capacité (ou une propriété, mais signifiant “qualité insortingnsèque”, pas dans le sens des propriétés C #) de l’object qui implémente l’interface. IAnimal n’est probablement pas un bon exemple pour une interface, mais IWalkable peut être une bonne interface à avoir si votre système a beaucoup de choses qui peuvent marcher. Vous pourriez avoir des classes dérivées d’Animal telles que Chien, Vache, Poisson, Serpent. Les deux premiers implémenteraient probablement IWalkable, les deux derniers ne marchent pas, alors ils ne le feraient pas. Maintenant, vous demandez “pourquoi ne pas avoir une autre super classe, WalkingAnimal, que Dog and Cow dérivent?”. La réponse est lorsque vous avez quelque chose de complètement en dehors de l’arbre d’inheritance qui peut également marcher, tel qu’un robot. Robot implémenterait IWalkable, mais ne dériverait probablement pas d’Animal. Si vous voulez une liste de choses qui peuvent marcher, vous devez la taper comme IWalkable et vous pouvez mettre tous les animaux et les robots dans la liste.

Maintenant, remplacez IWalkable par quelque chose de plus logiciel que IPersistable, et l’analogie devient beaucoup plus proche de ce que vous verriez dans un vrai programme.

Utilisez des interfaces lorsque les implémentations de la même fonctionnalité seront différentes.

Utilisez des classes abstraites / de base lorsque vous devez partager une implémentation concrète commune.

Pensez à une interface comme un contrat. C’est une façon de dire: “Ces classes doivent suivre ces règles.”

Donc, dans l’exemple IAnimal, c’est une façon de dire “Je DOIS pouvoir appeler Run, Walk, etc. sur les classes qui implémentent IAnimal.”

Pourquoi est-ce utile? Vous souhaiterez peut-être créer une fonction qui repose sur le fait que vous devez pouvoir appeler Run and Walk, par exemple, sur l’object. Vous pourriez avoir le suivant:

 public void RunThenWalk(Monkey m) { m.Run(); m.Walk(); } public void RunThenWalk(Dog d) { d.Run(); d.Walk(); } 

… et répète cela pour tous les objects que tu connais peuvent courir et marcher. Cependant, avec votre interface IAnimal, vous pouvez définir la fonction une fois comme suit:

 public void RunThenWalk(IAnimal a) { a.Run(); a.Walk(); } 

En programmant sur l’interface, vous faites essentiellement confiance aux classes pour implémenter l’intention de l’interface. Donc, dans notre exemple, la pensée est “Je me moque de la façon dont ils courent et marchent, tant qu’ils courent et marchent. Mon RunThenWalk sera valide tant qu’ils remplissent cet accord. Il fonctionne parfaitement sans savoir autre chose la classe.”

Il y a aussi une bonne discussion dans cette question connexe .

Ne vous inquiétez pas trop. Beaucoup de développeurs auront rarement besoin d’écrire une interface. Vous utiliserez fréquemment des interfaces disponibles dans le framework .NET , mais si vous ne ressentez pas le besoin d’en écrire un, cela n’a rien de surprenant.

L’exemple que je donne toujours à quelqu’un est si vous avez une classe de voilier et une classe de vipère. Ils héritent respectivement de la classe Bateau et de la classe Voiture. Maintenant, dites que vous devez parcourir tous ces objects et appeler leur méthode Drive() . Bien que vous puissiez écrire un code comme celui-ci:

 if(myObject is Boat) ((Boat)myObject).Drive() else if (myObject is Car) ((Car)myObject).Drive() 

Il serait beaucoup plus simple d’écrire:

 ((IDrivable)myObject).Drive() 

Jimmy a tout à fait raison de vouloir utiliser une seule variable pour plusieurs types, mais tous ces types implémentent la même méthode via une déclaration d’interface. Ensuite, vous pouvez les appeler méthode principale sur la variable typée d’interface.

Il y a cependant une deuxième raison d’utiliser des interfaces. Lorsque l’architecte du projet est une personne différente du codeur d’implémentation ou qu’il existe plusieurs codeurs d’implémentation et un chef de projet. Le responsable peut écrire tout un tas d’interfaces et voir que le système interagit, puis laisser les développeurs remplir les interfaces avec les classes d’implémentation. C’est le meilleur moyen de s’assurer que plusieurs personnes écrivent des classes compatibles et peuvent le faire en parallèle.

D’après mon expérience, la force mosortingce pour créer des interfaces ne s’est produite que lorsque j’ai commencé à faire des tests unitaires avec un cadre moqueur. Il est devenu évident que l’utilisation d’interfaces faciliterait beaucoup la tâche (puisque le cadre dépendait des méthodes virtuelles). Une fois que j’ai commencé, j’ai vu l’intérêt d’extraire l’interface de ma classe de l’implémentation. Même si je ne crée pas d’interface réelle, j’essaie maintenant de rendre mes méthodes virtuelles (en fournissant une interface implicite pouvant être remplacée).

Il y a beaucoup d’autres raisons pour lesquelles j’ai trouvé que renforcer les bonnes pratiques de la refactorisation des interfaces, mais les tests unitaires / les moqueries étaient ce qui constituait le «moment aha» de l’expérience pratique.

EDIT : Pour clarifier, avec les tests unitaires et les moqueries, j’ai toujours deux implémentations – l’implémentation réelle et concrète et une autre implémentation de simulation utilisée dans les tests. Une fois que vous avez deux implémentations, la valeur de l’interface devient évidente – prenez en compte l’interface pour pouvoir remplacer l’implémentation à tout moment. Dans ce cas, je le remplace par une interface fictive. Je sais que je peux le faire sans une interface réelle si ma classe est construite correctement, mais l’utilisation d’une interface réelle le renforce et le rend plus clair (plus clair pour le lecteur). Sans cet élan, je ne pense pas que j’aurais apprécié la valeur des interfaces puisque la plupart de mes classes seulement ont toujours une seule implémentation concrète.

J’aime l’analogie de l’armée.

Le sergent ne se soucie pas de savoir si vous êtes un développeur de logiciels , un musicien ou un avocat .
Vous êtes traité comme un soldat .

uml

Il est plus facile pour le sergent de ne pas se préoccuper des détails spécifiques des personnes avec lesquelles il travaille,
traitez tout le monde comme des abstractions de soldat (… et punissez-les quand ils n’agissent pas comme ceux-là).

La capacité des personnes à agir comme des soldats s’appelle le polymorphism.

Les interfaces sont des constructions de logiciels qui aident à obtenir un polymorphism.

Besoin de résumer les détails pour atteindre la simplicité est la réponse à votre question.

Le polymorphism , qui signifie étymologiquement “plusieurs formes”, est la capacité de traiter un object de toute sous-classe d’une classe de base comme s’il s’agissait d’un object de la classe de base. Une classe de base a donc beaucoup de formes: la classe de base elle-même et ses sous-classes.

(..) Cela rend votre code plus facile à écrire et plus facile à comprendre pour les autres. Cela rend également votre code extensible, car d’autres sous-classes pourraient être ajoutées ultérieurement à la famille de types, et les objects de ces nouvelles sous-classes fonctionneraient également avec le code existant.

Quelques exemples de non-programmation pouvant vous aider à voir les utilisations appropriées des interfaces dans la programmation.

Il y a une interface entre les appareils élecsortingques et le réseau élecsortingque – c’est l’ ensemble des conventions sur la forme des sockets et des sockets et les tensions / courants qui les traversent. Si vous souhaitez implémenter un nouvel appareil élecsortingque, tant que votre connecteur respecte les règles, il sera en mesure d’obtenir des services du réseau. Cela rend l’ extensibilité très facile et supprime ou réduit les coûts de coordination : vous n’avez pas à informer le fournisseur d’élecsortingcité du fonctionnement de votre nouvel appareil et à conclure un accord distinct sur la manière de twigr votre nouvel appareil sur le réseau.

Les pays ont des jauges ferroviaires standard. Cela permet une division du travail entre les sociétés d’ingénierie qui installent des rails et des sociétés d’ingénierie qui construisent des trains sur ces rails et permet aux entresockets ferroviaires de remplacer et de mettre à niveau les trains sans avoir à remettre en état l’ensemble du système.

Le service qu’une entreprise présente à un client peut être décrit comme une interface: une interface bien définie met l’accent sur le service et masque les moyens . Lorsque vous placez une lettre dans une boîte aux lettres, vous vous attendez à ce que le système postal livre la lettre dans un délai donné, mais vous n’avez aucune attente sur la manière dont la lettre est livrée: vous n’avez pas besoin de savoir Choisissez le moyen de livraison qui répond le mieux aux exigences et aux circonstances actuelles. Une exception à cela est la capacité des clients à choisir la poste aérienne – ce n’est pas le genre d’interface qu’un programmeur informatique moderne aurait conçu, car il révèle trop de la mise en œuvre.

Exemples tirés de la nature: Je ne suis pas très intéressé par les exemples eats (), makesSound (), Move (), etc. Ils décrivent le comportement, ce qui est correct, mais ils ne décrivent pas les interactions et la façon dont elles sont activées . Les exemples évidents d’interfaces qui permettent des interactions dans la nature sont liés à la reproduction, par exemple une fleur fournit une certaine interface à une abeille pour que la pollinisation puisse avoir lieu.

Il est tout à fait possible de passer toute votre vie en tant que développeur .net et de ne jamais écrire vos propres interfaces. Après tout, nous avons bien survécu sans eux pendant des décennies et nos langues étaient encore Turing-complet.

Je ne peux pas vous dire pourquoi vous avez besoin d’interfaces, mais je peux vous donner une liste des endroits où nous les utilisons dans notre projet actuel:

  1. Dans notre modèle de plug-in, nous chargeons les plug-ins par interface et fournissons cette interface aux auteurs de plug-ins pour qu’ils s’y conforment.

  2. Dans notre système de messagerie intermachine, les classes de messages implémentent toutes une interface spécifique et sont “déballées” à l’aide de l’interface.

  3. Notre système de gestion de la configuration définit une interface utilisée pour définir et récupérer les parameters de configuration.

  4. Nous avons une interface que nous utilisons pour éviter un problème de référence circulaire désagréable. (Ne fais pas ça si tu n’es pas obligé.)

Je suppose que s’il y a une règle, c’est d’utiliser des interfaces lorsque vous souhaitez regrouper plusieurs classes dans une relation is-a, mais vous ne voulez fournir aucune implémentation dans la classe de base.

Un exemple de code (combinaison de celui d’Andrew avec un des miens à la fonction des interfaces ), qui explique également pourquoi l’interface plutôt qu’une classe abstraite sur les langages sans prise en charge de l’inheritance multiple (c # et Java):

 interface ILogger { void Log(); } class FileLogger : ILogger { public void Log() { } } class DataBaseLogger : ILogger { public void Log() { } } public class MySpecialLogger : SpecialLoggerBase, ILogger { public void Log() { } } 

Notez que FileLogger et DataBaseLogger n’ont pas besoin de l’interface (peut être une classe de base abstraite de Logger). Mais considérez que vous devez utiliser un enregistreur tiers qui vous oblige à utiliser une classe de base (disons qu’il expose les méthodes protégées que vous devez utiliser). Comme le langage ne prend pas en charge l’inheritance multiple, vous ne pourrez pas utiliser l’approche de classe de base abstraite.

En résumé, utilisez une interface si possible pour obtenir une flexibilité supplémentaire sur votre code. Votre implémentation est moins liée, donc elle convient mieux au changement.

J’ai utilisé des interfaces de temps en temps et voici ma dernière utilisation (les noms ont été généralisés):

J’ai un tas de contrôles personnalisés sur un WinForm qui doivent enregistrer des données sur mon object métier. Une approche consiste à appeler chaque contrôle séparément:

 myBusinessObject.Save(controlA.Data); myBusinessObject.Save(controlB.Data); myBusinessObject.Save(controlC.Data); 

Le problème avec cette implémentation est que chaque fois que j’ajoute un contrôle, je dois aller dans ma méthode “Save Data” et append le nouveau contrôle.

J’ai changé mes contrôles pour implémenter une interface ISaveable qui a une méthode SaveToBusinessObject (…), donc maintenant, ma méthode “Save Data” ne fait que parcourir les contrôles et si elle en trouve un qui est ISaveable, il appelle SaveToBusinessObject. Alors maintenant, lorsqu’un nouveau contrôle est nécessaire, tout ce que quelqu’un doit faire, c’est implémenter ISaveable dans cet object (et ne jamais toucher une autre classe).

 foreach(Control c in Controls) { ISaveable s = c as ISaveable; if( s != null ) s.SaveToBusinessObject(myBusinessObject); } 

L’avantage souvent non réalisé pour les interfaces est que vous localisez les modifications. Une fois défini, vous modifierez rarement le stream global d’une application, mais vous apporterez souvent des modifications au niveau des détails. Lorsque vous conservez les détails dans des objects spécifiques, une modification de ProcessA n’affecte pas une modification de ProcessB. (Les classes de base vous donnent également cet avantage.)

EDIT: Un autre avantage est la spécificité dans les actions. Comme dans mon exemple, tout ce que je veux faire, c’est enregistrer les données; Je ne me soucie pas de quel type de contrôle il s’agit ou s’il peut faire autre chose – je veux juste savoir si je peux enregistrer les données dans le contrôle. Cela rend mon code de sauvegarde assez clair – il n’y a pas de vérification pour voir s’il s’agit de texte, numérique, booléen ou autre, car le contrôle personnalisé gère tout cela.

Vous devez définir une interface une fois que vous devez forcer un comportement pour votre classe.

Le comportement d’un animal peut impliquer marcher, manger, courir, etc. Par conséquent, vous les définissez comme des interfaces.

Un autre exemple pratique est l’interface ActionListener (ou Runnable). Vous les metsortingez en œuvre lorsque vous devez suivre un événement particulier. Par conséquent, vous devez fournir l’implémentation de la actionPerformed(Event e) dans votre classe (ou sous-classe). De même, pour l’interface Runnable, vous fournissez l’implémentation de la méthode public void run() .

En outre, vous pouvez avoir ces interfaces implémentées par un nombre quelconque de classes.

Une autre instance où les interfaces sont utilisées (en Java) consiste à implémenter l’inheritance multiple offert en C ++.

Supposons que vous vouliez modéliser les désagréments susceptibles de se produire lorsque vous essayez de vous coucher.

Modèle avant interfaces

entrer la description de l'image ici

 class Mosquito { void flyAroundYourHead(){} } class Neighbour{ void startScreaming(){} } class LampJustOutsideYourWindow(){ void shineJustThroughYourWindow() {} } 

Comme vous voyez clairement que beaucoup de «choses» peuvent être ennuyantes lorsque vous essayez de dormir.

Utilisation de classes sans interfaces

Mais quand il s’agit d’utiliser ces classes, nous avons un problème. Il n’ont rien en commun. Vous devez appeler chaque méthode séparément.

 class TestAnnoyingThings{ void testAnnoyingThinks(Mosquito mosquito, Neighbour neighbour, LampJustOutsideYourWindow lamp){ if(mosquito != null){ mosquito.flyAroundYourHead(); } if(neighbour!= null){ neighbour.startScreaming(); } if(lamp!= null){ lamp.shineJustThroughYourWindow(); } } } 

Modèle avec interfaces

Pour surmonter ce problème, nous pouvons introduire une iterface entrer la description de l'image ici

 interface Annoying{ public void annoy(); } 

Et l’implémenter dans des classes

 class Mosquito implements Annoying { void flyAroundYourHead(){} void annoy(){ flyAroundYourHead(); } } class Neighbour implements Annoying{ void startScreaming(){} void annoy(){ startScreaming(); } } class LampJustOutsideYourWindow implements Annoying{ void shineJustThroughYourWindow() {} void annoy(){ shineJustThroughYourWindow(); } } 

Utilisation avec des interfaces

Ce qui facilitera grandement l’utilisation de ces classes

 class TestAnnoyingThings{ void testAnnoyingThinks(Annoying annoying){ annoying.annoy(); } } 

L’exemple le plus simple est celui des processeurs de paiement (Paypal, PDS, etc.).

Supposons que vous créez une interface IPaymentProcessor avec les méthodes ProcessACH et ProcessCreditCard.

Vous pouvez maintenant implémenter une implémentation concrète de Paypal. Ces méthodes appellent des fonctions spécifiques à PayPal.

Si vous décidez plus tard de changer de fournisseur, vous pouvez le faire. Créez simplement une autre implémentation concrète pour le nouveau fournisseur. Étant donné que tout ce qui vous concerne est votre interface (contrat), vous pouvez échanger celle utilisée par votre application sans changer le code qui la consum.

Il vous permet également d’effectuer des tests unitaires simulés (.Net). Si votre classe utilise une interface, vous pouvez simuler l’object dans vos tests unitaires et tester facilement la logique (sans réellement toucher la firebase database ou le service Web, etc.).

http://www.nmock.org/

Si vous parcourez les assemblys .NET Framework et explorez les classes de base des objects standard, vous remarquerez de nombreuses interfaces (membres nommés ISomeName).

Les interfaces servent essentiellement à mettre en place des frameworks, grands ou petits. J’ai ressenti la même chose à propos des interfaces jusqu’à ce que je veuille écrire mon propre framework. J’ai également constaté que la compréhension des interfaces m’a aidé à apprendre les frameworks beaucoup plus rapidement. Au moment où vous voulez écrire une solution plus élégante pour à peu près n’importe quoi, vous constaterez qu’une interface a beaucoup de sens. C’est comme une méthode permettant à une classe de mettre les vêtements appropriés pour le travail. Plus important encore, les interfaces permettent aux systèmes de devenir beaucoup plus auto-documentés, car les objects complexes deviennent moins complexes lorsque la classe implémente des interfaces, ce qui aide à classer ses fonctionnalités.

Les classes implémentent des interfaces lorsqu’elles veulent pouvoir participer à un framework de manière explicite ou explicite. Par exemple, IDisposable est une interface commune qui fournit une signature de méthode pour la méthode Dispose () populaire et utile. Dans un framework, tout ce que vous ou un autre développeur devez savoir sur une classe, c’est que si elle implémente IDisposable, alors vous savez que ((IDisposable) myObject) .Dispose () est disponible pour être appelé à des fins de nettoyage.

EXEMPLE CLASSIQUE: sans implémenter l’interface IDisposable, vous ne pouvez pas utiliser la construction de mot clé “using ()” en C #, car elle requirejs que tout object spécifié en tant que paramètre puisse être implicitement converti en IDisposable.

EXEMPLE COMPLEXE: Un exemple plus complexe serait la classe System.ComponentModel.Component. Cette classe implémente à la fois IDisposable et IComponent. La plupart des objects .NET, sinon tous, qui sont associés à un concepteur visuel, implémentent IComponent afin que l’EDI puisse interagir avec le composant.

CONCLUSION: Au fur et à mesure que vous vous familiarisez avec .NET Framework, la première chose à faire lorsque vous rencontrez une nouvelle classe dans l’explorateur d’objects ou dans l’outil .NET Reflector (gratuit) ( http://www.red-gate.com / products / reflector / ) consiste à vérifier la classe dont il hérite et les interfaces qu’il implémente. .NET Reflector est encore meilleur que l’Explorateur d’objects car il vous permet également de voir les classes dérivées. Cela vous permet de vous familiariser avec tous les objects qui dérivent d’une classe particulière, apprenant ainsi potentiellement des fonctionnalités de framework que vous ne connaissiez pas. Cela est particulièrement important lorsque des espaces de noms mis à jour ou nouveaux sont ajoutés au .NET Framework.

Considérez que vous faites un jeu de tir à la première personne. Le joueur a le choix entre plusieurs armes à feu.

On peut avoir une interface Gun qui définit une fonction shoot() .

Nous avons besoin de différentes sous-classes de classe Gun , à savoir ShotGun Sniper et ainsi de suite.

 ShotGun implements Gun{ public void shoot(){ \\shotgun implementation of shoot. } } Sniper implements Gun{ public void shoot(){ \\sniper implementation of shoot. } } 

Classe de tir

Le tireur a toutes les armes dans son armure. Permet de créer une List pour le représenter.

 List listOfGuns = new ArrayList(); 

Le tireur parcourt ses armes, au besoin, en utilisant la fonction switchGun()

 public void switchGun(){ //code to cycle through the guns from the list of guns. currentGun = //the next gun in the list. } 

Nous pouvons définir le Gun actuel en utilisant la fonction ci-dessus et appeler simplement la fonction shoot() lorsque fire() est appelé.

 public void fire(){ currentGun.shoot(); } 

Le comportement de la fonction de prise de vue variera selon les différentes implémentations de l’interface du Gun .

Conclusion

Créez une interface lorsqu’une fonction de classe dépend d’ une fonction d’une autre classe , qui est soumise à un changement de comportement, en fonction de l’instance (object) de la classe implémentée.

Par exemple, la fonction fire() de la classe Shooter attend des fusils ( Sniper , ShotGun ) qu’ils implémentent la fonction shoot() . Donc, si nous allumons le pistolet et le feu.

 shooter.switchGun(); shooter.fire(); 

Nous avons changé le comportement de la fonction fire() .

Pour développer ce que Larsenal a dit. Une interface est un contrat que toutes les classes d’implémentation doivent suivre. De ce fait, vous pouvez utiliser une technique appelée programmation dans le contrat. Cela permet à votre logiciel de devenir indépendant de l’implémentation.

Les interfaces sont généralement utilisées lorsque vous souhaitez définir un comportement que les objects peuvent présenter.

L’interface IDisposable , utilisée sur toutes les classes Microsoft qui utilisent des ressources système devant être libérées manuellement, en est un bon exemple. Cela nécessite que la classe qui l’implémente ait une méthode Dispose ().

(La méthode Dispose () est également appelée par la construction du langage using pour VB.NET et C # , qui ne fonctionne que sur IDisposable s)

Gardez à l’esprit que vous pouvez vérifier si un object implémente une interface spécifique en utilisant des constructions telles que TypeOf ... Is (VB.NET), is (C #), instanceof (Java), etc …

Comme plusieurs personnes ont probablement déjà répondu, des interfaces peuvent être utilisées pour appliquer certains comportements entre classes qui ne mettront pas en œuvre ces comportements de la même manière. Donc, en implémentant une interface, vous dites que votre classe a le comportement de l’interface. L’interface IAnimal ne serait pas une interface typique car les classes Chien, Chat, Oiseau, etc. sont des types d’animaux, et devraient probablement l’étendre, ce qui est un cas d’inheritance. Au lieu de cela, une interface ressemblerait plus à un comportement animal dans ce cas, comme IRunnable, IFlyable, ITrainable, etc.

Les interfaces sont bonnes pour beaucoup de choses, l’une des choses clés est la pluggability. Par exemple, si vous déclarez une méthode avec un paramètre List, tout ce qui implémentera l’interface List sera autorisé, ce qui permettra au développeur de supprimer et de connecter ultérieurement une liste différente sans avoir à réécrire une tonne de code.

Il est possible que vous n’utilisiez jamais d’interfaces, mais si vous concevez un projet à partir de zéro, en particulier dans un cadre quelconque, vous voudrez probablement vous familiariser avec eux.

Je vous recommande de lire le chapitre sur les interfaces dans Java Design de Coad, Mayfield et Kern. Ils l’expliquent un peu mieux que le texte d’introduction moyen. Si vous n’utilisez pas Java, vous pouvez simplement lire le début du chapitre, qui est principalement constitué de concepts.

Comme toutes les techniques de programmation qui ajoutent de la flexibilité à votre système, les interfaces ajoutent également un certain niveau de complexité. Ils sont souvent géniaux et vous pouvez les utiliser partout (vous pouvez créer une interface pour toutes vos classes) – mais en agissant ainsi, vous créerez un système plus complexe et plus difficile à gérer.

Il y a un compromis ici, comme d’habitude: la flexibilité sur la maintenabilité. Lequel est le plus important? Il n’y a pas de réponses – cela dépend du projet. Mais rappelez-vous que tous les logiciels devront être conservés …

Donc, mon conseil: n’utilisez pas les interfaces tant que vous n’en avez pas vraiment besoin. (Avec Visual Studio, vous pouvez extraire une interface d’une classe existante en 2 secondes – alors ne vous pressez pas.)

Cela dit, quand avez-vous besoin de créer une interface?

Je le fais quand je refactore une méthode qui doit subitement traiter deux classes similaires ou plus. Je crée ensuite une interface, assigne cette interface aux deux classes similaires (ou plus) et modifie le type de paramètre de la méthode (remplace le type de classe par le type d’interface).

Et ça marche: o)

Une exception: quand je me moque des objects, l’interface est beaucoup plus facile à utiliser. Donc, je crée souvent une interface juste pour cela.

PS: quand j’écris “interface”, je veux dire: “interface de toute classe de base”, y compris les classes d’interface pures. Notez que les classes abstraites sont souvent un meilleur pari que des interfaces pures puisque vous pouvez leur append de la logique.

Cordialement, Sylvain.

Les interfaces deviendront évidentes quand vous deviendrez un développeur de bibliothèque (quelqu’un qui code pour d’autres codeurs). La plupart d’entre nous commençons en tant que développeurs d’applications , où nous utilisons des API et des bibliothèques de programmation existantes.

Dans le même ordre d’idées que les interfaces sont un contrat , personne n’a encore mentionné que les interfaces sont un excellent moyen de rendre certaines parties de votre code stables . C’est particulièrement utile lorsqu’il s’agit d’un projet d’ équipe (ou lorsque vous développez du code utilisé par d’autres développeurs). Alors, voici un scénario concret pour vous:

Lorsque vous développez du code dans une équipe , d’autres utilisateurs utiliseront peut-être le code que vous écrivez. Ils seront ravis quand ils coderont pour vos interfaces (stables), et vous serez heureux si vous avez la liberté de modifier vos implémentations (cachées derrière l’interface) sans casser le code de votre équipe. C’est une variante du masquage des informations (les interfaces sont publiques, les implémentations sont masquées par les programmeurs clients). En savoir plus sur les variantes protégées .

Voir également cette question connexe sur le codage d’une interface .

Il y a tellement de raisons d’utiliser une interface.

  1. Utiliser dans le comportement polymorphe. Où vous voulez appeler des méthodes spécifiques d’une classe enfant avec une interface ayant une référence à la classe enfant.

  2. Avoir un contrat avec des classes pour implémenter toutes les méthodes où cela est nécessaire, comme c’est le cas pour les objects COM, où une classe de wrapper est générée sur une DLL qui hérite de l’interface; ces méthodes sont appelées en arrière-plan et il vous suffit de les implémenter, mais avec la même structure que celle définie dans la DLL COM que vous ne pouvez connaître que via l’interface qu’elles exposent.

  3. Réduire l’utilisation de la mémoire en chargeant des méthodes spécifiques dans une classe. Comme si vous avez trois objects métier et qu’ils sont implémentés dans une seule classe, vous pouvez utiliser trois interfaces.

Par exemple, IUser, IOrder, IOrderItem

 public interface IUser() { void AddUser(ssortingng name ,ssortingng fname); } // Same for IOrder and IOrderItem // public class BusinessLayer: IUser, IOrder, IOrderItem { public void AddUser(ssortingng name ,ssortingng fname) { // Do stuffs here. } // All methods from all interfaces must be implemented. } 

Si vous voulez seulement append un utilisateur, faites comme ceci:

 IUser user = new (IUser)BusinessLayer(); // It will load all methods into memory which are declared in the IUser interface. user.AddUser();