Comment saurai-je quand créer une interface?


196

J'en suis à un stade de mon apprentissage du développement où je sens que je dois en savoir plus 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 une interface IAnimal pour des choses comme 'Walk', 'Run', 'GetLegs', etc. - mais je n'ai jamais travaillé sur quelque chose et je me suis dit "Hé, je devrais utiliser une interface 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 pourrais ne jamais réaliser un besoin concret pour un - principalement en raison d'un aspect manquant de leur compréhension! Cela me donne l'impression de manquer quelque chose en haut en tant que développeur! Si quelqu'un a eu une expérience comme celle-ci et a fait une percée, j'apprécierais quelques conseils sur la façon de comprendre ce concept. Je vous remercie.


Réponses:


151

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 faire implémenter IProcessable, puis faire

List<IProcessable> list;

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

cela évoluera beaucoup mieux lorsque vous ajoutez, disons, 50 types de classes qui font toutes la même chose.


Un autre problème concret:

Avez-vous déjà jeté un œil à 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 prends en charge 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.


2
Ça aide. Quel est l'avantage d'avoir une interface présente plutôt que d'avoir les types ayant tous une implémentation pour la méthode Process ()?
user53885

Vous ne pourriez pas utiliser la même variable p à moins que ce ne soient toutes des sous-classes du même type de base ou qu'elles aient implémenté l'interface.
Karl

Vous n'avez pas à lancer, contrairement à 50 classes différentes avec une méthode Process. C # n'utilise pas le "typage canard", donc simplement parce que A a Process () et B a Process () ne signifie pas qu'il existe un moyen générique d'appeler non plus. Vous avez besoin d'une interface pour cela.
user7116

droite. Je viens de changer "var" en "IProcessable" pour donner plus de sens à l'exemple.
Jimmy

2
@Rogerio: J'essayais d'être générique. Le point n'est pas que "quand vous avez des choses qui ont une fonction Process ()" c'est "quand vous avez des choses qui partagent un ensemble commun de méthodes". l'exemple peut facilement être changé enforeach(IMyCompanyWidgetFrobber a in list) a.Frob(widget, context);
Jimmy

133

J'aime beaucoup la réponse de Jimmy, mais je sens que je dois y ajouter quelque chose. La clé de tout cela est le "capable" dans IProcess capable. Il indique une capacité (ou propriété, mais signifiant «qualité intrinsèque», pas au sens de propriétés C #) de l'objet 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 cours dérivés d'animaux tels que chien, vache, poisson, serpent. Les deux premiers implémenteraient probablement IWalkable, les deux derniers ne marchent pas, donc ils ne le feraient pas. Maintenant vous demandez "pourquoi ne pas simplement avoir une autre superclasse, WalkingAnimal, dont dérivent Dog and Cow?". La réponse est lorsque vous avez quelque chose de complètement en dehors de l'arbre d'héritage qui peut également marcher, comme un robot. Robot implémenterait IWalkable, mais ne dériverait probablement pas d'Animal. Si vous voulez une liste de choses qui peuvent marcher,

Remplacez maintenant IWalkable par quelque chose de plus logiciel comme IPersistable, et l'analogie devient beaucoup plus proche de ce que vous verriez dans un vrai programme.


9
J'aime ce que vous avez proposé - "Cela indique une capacité". Les interfaces sont vraiment nécessaires lorsque vous devez définir la capacité, car les bases doivent s'en tenir à sa classe "Base".
Ramiz Uddin

72

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

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


8
Le premier est appelé polymorphisme. La deuxième est l'huile de serpents - à moins que la sous-classe ne soit une classe de base (il n'y a pas de violation du principe de substitution de Liskov), vous devriez privilégier la composition plutôt que l'héritage.
Arnis Lapsa

@ArnisLapsa Je ne comprends pas très bien ce que vous entendez par "à moins que la sous-classe ne soit une classe de base". Quand une sous-classe ne serait-elle pas "une" classe de base? (comme dans le ismot - clé)
Marc.2377

32

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

Ainsi, dans l'exemple IAnimal, c'est une façon de dire: "Je DOIS être capable d'appeler Run, Walk, etc. sur des 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'objet. Vous pourriez avoir les éléments suivants:

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

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

... et répétez cela pour tous les objets que vous savez pouvoir 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 contre 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 fiche de savoir comment ils courent et marchent, tant qu'ils courent et marchent. Mon RunThenWalk sera valide tant qu'ils respecteront cet accord. Il fonctionne parfaitement bien sans rien savoir d'autre la classe."

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


1
N'oubliez pas l'indépendance de la mise en œuvre. Une interface permet de ne pas se soucier de la façon dont la fonction sous-jacente est implémentée, juste qu'elle fait ce que l'interface dit qu'elle fait.
Matthew Brubaker le

18

Ne t'inquiète pas autant. 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 une de sitôt, il n'y a rien de surprenant à cela.

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 Boat et de la classe Car. Maintenant, dites que vous devez parcourir tous ces objets et appeler leur Drive()méthode. Bien que vous puissiez écrire du 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()

16

Jimmy a raison, lorsque vous voulez pouvoir 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 de 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 le soin aux développeurs de remplir les interfaces avec les classes d'implémentation. C'est le meilleur moyen de garantir que plusieurs personnes écrivent des classes compatibles et qu'elles peuvent le faire en parallèle.


15

J'aime l'analogie avec l'armée.

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

uml

Il est plus facile pour le sergent de ne pas se soucier des détails spécifiques des personnes avec
lesquelles il travaille, de traiter tout le monde comme des abstractions de soldat (... et de les punir lorsqu'ils ne se comportent pas comme ceux-là).

La capacité des personnes à agir comme des soldats est appelée polymorphisme.

Les interfaces sont des constructions logicielles qui aident à réaliser le polymorphisme.

Besoin d'abstraire les détails afin d'atteindre la simplicité est la réponse à votre question.

Le polymorphisme , qui signifie étymologiquement «plusieurs formes», est la capacité de traiter un objet de n'importe quelle sous-classe d'une classe de base comme s'il s'agissait d'un objet de la classe de base. Une classe de base a donc plusieurs formes: la classe de base elle-même et n'importe laquelle de ses sous-classes.

(..) Cela rend votre code plus facile à écrire et à 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 objets de ces nouvelles sous-classes fonctionneraient également avec le code existant.


14

D'après mon expérience, la force motrice pour créer des interfaces ne s'est produite que lorsque j'ai commencé à faire des tests unitaires avec un cadre de simulation. Il est devenu très clair que l'utilisation d'interfaces allait rendre la moquerie beaucoup plus facile (puisque le cadre dépendait des méthodes étant virtuelles). Une fois que j'ai commencé, j'ai vu la valeur d'abstraire 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 (fournissant une interface implicite qui peut être remplacée).

Il y a beaucoup d'autres raisons que j'ai trouvées pour renforcer la bonne pratique du refactoring vers les interfaces, mais le test unitaire / la simulation était ce qui a fourni le "moment aha" initial de l'expérience pratique.

EDIT : Pour clarifier, avec les tests unitaires et la simulation, j'ai toujours deux implémentations - l'implémentation réelle et concrète et une autre implémentation simulée utilisée dans les tests. Une fois que vous avez deux implémentations, la valeur de l'interface devient évidente - traitez-la en termes d'interface afin de pouvoir remplacer l'implémentation à tout moment. Dans ce cas, je le remplace par une interface factice. Je sais que je peux le faire sans interface réelle si ma classe est construite correctement, mais l'utilisation d'une interface réelle renforce cela et le rend plus propre (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 jamais une seule implémentation concrète.


Bonne chose pour de mauvaises raisons. Dans votre cas - vous vous retrouvez avec ce que l'on appelle des «interfaces d'en-tête» et une sur-pondération de complexité supplémentaire a permis d'atteindre la simplicité.
Arnis Lapsa

@Arnis - les tests unitaires sont une "mauvaise raison", se moquer facilement des classes pour supprimer les dépendances dans les tests est une "mauvaise raison". Désolé, mais je ne suis pas d'accord.
tvanfosson

1
les tests doivent influencer indirectement la conception en fournissant des informations en retour si le code est ou non testable. ajouter des points d'extensibilité pour améliorer la testabilité elle-même revient à tricher. Je pense que Mark Seeman le résume le mieux bit.ly/esi8Wp
Arnis Lapsa

1
@Arnis - utilisez-vous donc des simulateurs dans vos tests unitaires? Sinon, comment supprimez-vous une dépendance aux dépendances. Utilisez-vous DI? Les tests unitaires m'ont conduit à utiliser la moquerie et l'ID; la moquerie et l'ID ont prouvé la valeur de la bonne pratique d'utiliser des interfaces pour définir des contrats d'une manière qu'aucune compréhension académique ne pourrait jamais. En raison de mon adoption de TDD, mon code est beaucoup moins couplé qu'il ne l'aurait été autrement. Je pense que c'est une bonne chose.
tvanfosson

dire simplement que la décomposition qui n'est pas le long des soi-disant joints naturels conduit à une faible cohésion et à une complexité inutile.
Arnis Lapsa

10

Quelques exemples hors programmation qui pourraient vous aider à voir les utilisations appropriées des interfaces dans la programmation.

Il existe une interface entre les appareils électriques et le réseau électrique - c'est l' ensemble des conventions concernant la forme des fiches et des prises et les tensions / courants qui les traversent. Si vous souhaitez mettre en œuvre un nouvel appareil électrique, tant que votre prise suit les règles, elle pourra 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'électricité sur le fonctionnement de votre nouvel appareil et à conclure un accord séparé sur la façon de connecter votre nouvel appareil au réseau.

Les pays ont des jauges de rail standard. Cela permet une division du travail entre les sociétés d'ingénierie qui posent des rails et les sociétés d'ingénierie qui construisent des trains pour circuler sur ces rails, et cela permet aux sociétés ferroviaires de remplacer et de moderniser les trains sans avoir à réorganiser 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 cache les moyens . Lorsque vous mettez une lettre dans une boîte aux lettres, vous vous attendez à ce que le système postal remette la lettre dans un délai donné, mais vous n'avez aucune attente quant à la façon dont la lettre est livrée: vous n'avez pas besoin de savoir , et le service postal a la flexibilité de choisir 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 type d'interface qu'un programmeur informatique moderne aurait conçu, car il révèle trop de la mise en œuvre.

Exemples de la nature: je ne suis pas trop intéressé par les exemples eats (), makeSound (), moves (), etc. Ils décrivent le comportement, ce qui est correct, mais ils ne décrivent pas les interactions et la façon dont ils sont activés . 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.


5

Il est tout à fait possible de passer votre vie entière 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-complete.

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 rédacteurs de plug-in 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épliées" à l'aide de l'interface.

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

  4. Nous avons une interface que nous utilisons pour éviter un problème de référence circulaire désagréable. (Ne faites pas cela si vous n'êtes 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 pas fournir d'implémentation dans la classe de base.


5

Un exemple de code (combinaison d'Andrew avec un extra de moi à ce qui est le but des interfaces ), qui explique également pourquoi l'interface au lieu d'une classe abstraite sur les langues sans prise en charge de l'héritage 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 (il peut s'agir d'une classe de base abstraite 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'héritage multiple, vous ne pourrez pas utiliser l'approche de classe de base abstraite.

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


4

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 dans mon objet 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 entrer dans ma méthode "Enregistrer les données" et ajouter le nouveau contrôle.

J'ai changé mes contrôles pour implémenter une interface ISaveable qui a une méthode SaveToBusinessObject (...) alors maintenant ma méthode "Save Data" itère simplement à travers les contrôles et si elle en trouve un qui est ISaveable, elle appelle SaveToBusinessObject. Alors maintenant, quand un nouveau contrôle est nécessaire, tout ce que quelqu'un a à faire est d'implémenter ISaveable dans cet objet (et de 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é des interfaces est que vous localisez les modifications. Une fois défini, vous modifiez rarement le flux global d'une application, mais vous apportez souvent des modifications au niveau des détails. Lorsque vous conservez les détails dans des objets spécifiques, un changement dans ProcessA n'affectera pas un changement dans ProcessB. (Les cours de base vous offrent également cet avantage.)

EDIT: Un autre avantage est la spécificité des actions. Comme dans mon exemple, tout ce que je veux faire, c'est sauvegarder les données; Peu m'importe le type de contrôle ou s'il peut faire autre chose - je veux juste savoir si je peux sauvegarder 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 parce que le contrôle personnalisé gère tout cela.


4

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

Le comportement d'un animal peut impliquer de 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 mettriez en œuvre lorsque vous aurez besoin de suivre un événement particulier. Par conséquent, vous devez fournir l'implémentation de la actionPerformed(Event e)méthode dans votre classe (ou sous-classe). De même, pour l'interface Runnable, vous fournissez l'implémentation de la public void run()méthode.

En outre, ces interfaces peuvent être implémentées par n'importe quel nombre de classes.

Une autre instance où des interfaces sont utilisées (en Java) est d'implémenter l'héritage multiple offert en C ++.


3
S'il vous plaît, Dieu les oblige à arrêter de dire des choses comme l'héritage multiple en ce qui concerne les interfaces. Vous N'héritez PAS d' une interface dans une classe. Vous le mettez en œuvre.
Andrei Rînea

4

Supposons que vous souhaitiez modéliser les désagréments qui peuvent survenir lorsque vous essayez de vous endormir.

Modéliser avant les interfaces

entrez la description de l'image ici

class Mosquito {
    void flyAroundYourHead(){}
}

class Neighbour{
    void startScreaming(){}
}

class LampJustOutsideYourWindow(){
    void shineJustThroughYourWindow() {}
}

Comme vous le voyez clairement, beaucoup de «choses» peuvent être ennuyeuses 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 iterfaceentrez la description de l'image ici

interface Annoying{
   public void annoy();

}

Et l'implémenter à l'intérieur 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 rendra l'utilisation de ces classes beaucoup plus facile

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

D'accord, mais ne doit pas Neighbouret doit LampJustOutsideYourWindowégalement être implémenté Annoying?
Stardust

Oui, merci de l'avoir signalé. J'ai effectué une modification avec ce changement
Marcin Szymczak

2

L'exemple le plus simple à donner est quelque chose comme les processeurs de paiement (Paypal, PDS, etc.).

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

Vous pouvez désormais implémenter une implémentation concrète de Paypal. Faire en sorte que ces méthodes appellent des fonctions spécifiques à PayPal.

Si vous décidez plus tard que vous devez passer à un autre fournisseur, vous le pouvez. Créez simplement une autre implémentation concrète pour le nouveau fournisseur. Étant donné que vous n'êtes lié qu'à votre interface (contrat), vous pouvez échanger celle que votre application utilise sans changer le code qui la consomme.


2

Il vous permet également d'effectuer des tests unitaires fictifs (.Net). Si votre classe utilise une interface, vous pouvez vous moquer de l'objet dans vos tests unitaires et tester facilement la logique (sans réellement toucher la base de données ou le service Web, etc.).

http://www.nmock.org/


2

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

Les interfaces sont essentiellement destinées à la mise en œuvre de cadres, grands ou petits. J'ai ressenti la même chose à propos des interfaces jusqu'à ce que je veuille écrire un cadre personnel. 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 pour laisser une classe 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 objets 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 implicite. Par exemple, IDisposable est une interface commune qui fournit la 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, 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 nécessite que tout objet spécifié comme 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, sinon la totalité, des objets .NET associés à un concepteur visuel implémentent IComponent afin que l'EDI puisse interagir avec le composant.

CONCLUSION: À mesure que vous vous familiariserez avec le .NET Framework, la première chose que vous ferez lorsque vous rencontrerez une nouvelle classe dans l'Explorateur d'objets ou dans l'outil (gratuit) .NET Reflector ( http://www.red-gate.com / products / reflector / ) consiste à vérifier de quelle classe il hérite et aussi les interfaces qu'il implémente. Le réflecteur .NET est encore meilleur que l'explorateur d'objets car il vous permet également de voir les classes dérivées. Cela vous permet d'en savoir plus sur tous les objets qui dérivent d'une classe particulière, et ainsi potentiellement de découvrir des fonctionnalités de framework dont vous ignoriez l'existence. Cela est particulièrement important lorsque des espaces de noms mis à jour ou nouveaux sont ajoutés au .NET Framework.


2

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

Nous pouvons avoir une interface Gunqui définit une fonction shoot().

Nous avons besoin de différentes sous-classes de Gunclasse à savoir ShotGun Sniperet 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 tous les pistolets dans son armure. Permet de créer un Listpour le représenter.

List<Gun> listOfGuns = new ArrayList<Gun>();

Le tireur parcourt ses armes, au fur et à mesure des besoins, 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 pistolet actuel, en utilisant la fonction ci-dessus et simplement appeler la shoot()fonction, quand fire()est appelé.

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

Le comportement de la fonction de prise de vue variera en fonction des différentes implémentations de l' Guninterface.

Conclusion

Créez une interface, lorsqu'une fonction de classe dépend d' une fonction d'une autre classe , qui est soumise à changer son comportement, en fonction de l'instance (objet) de la classe implémentée.

par exemple, la fire()fonction de la Shooterclasse attend des pistolets ( Sniper, ShotGun) qu'ils implémentent la shoot()fonction. Donc, si nous passons le pistolet et tirons.

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

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


1

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


1

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

Un bon exemple de cela dans le monde .NET est l' interface IDisposable , qui est utilisée sur toutes les classes Microsoft qui utilisent des ressources système qui doivent être libérées manuellement. Il 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 utilisant pour VB.NET et C # , qui ne fonctionne que sur IDisposables)

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


1

Comme plusieurs personnes ont probablement déjà répondu, les interfaces peuvent être utilisées pour appliquer certains comportements entre classes qui n'implémenteront pas 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'héritage. Au lieu de cela, une interface ressemblerait plus au comportement animal dans ce cas, comme IRunnable, IFlyable, ITrainable, etc.

Les interfaces sont bonnes pour de nombreuses choses, l'un des éléments clés est la connectabilité. Par exemple, déclarer une méthode qui a un paramètre List permettra à tout ce qui implémente l'interface List d'être transmis, permettant au développeur de supprimer et de brancher une liste différente ultérieurement 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 un cadre quelconque, vous voudrez probablement vous familiariser avec elles.

Je recommanderais de lire le chapitre sur les interfaces dans Java Design par 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 n'est que principalement des concepts.


1

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 l'utiliser partout (vous pouvez créer une interface pour toutes vos classes) - mais ce faisant, vous créeriez un système plus complexe qui serait plus difficile à maintenir.

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

Donc, mon conseil: n'utilisez pas les interfaces avant d'en avoir vraiment besoin. (Avec Visual Studio, vous pouvez extraire une interface d'une classe existante en 2 secondes - alors ne vous précipitez pas.)

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

Je le fais lorsque je refactorise une méthode qui doit soudainement traiter deux ou plusieurs classes similaires. Je crée ensuite une interface, attribue cette interface aux deux (ou plus) classes similaires et je change le type de paramètre de méthode (remplacez le type de classe par le type d'interface).

Et ça marche: o)

Une exception: lorsque je me moque des objets, les interfaces sont beaucoup plus faciles à utiliser. Je crée donc souvent une interface juste pour cela.

PS: quand j'écris "interface", je veux dire: "interface de n'importe quelle classe de base", y compris les classes d'interface pures. Notez que les classes abstraites sont souvent un meilleur pari que les interfaces pures puisque vous pouvez leur ajouter de la logique.

Cordialement, Sylvain.


1

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

Dans la même veine que les interfaces sont un contrat , personne n'a encore mentionné que les interfaces sont un excellent moyen de stabiliser certaines parties de votre code . Cela 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). Voici donc un scénario concret pour vous:

Lorsque vous développez du code en équipe , d'autres utiliseront peut-être le code que vous écrivez. Ils seront plus heureux lorsqu'ils coderont sur vos interfaces (stables), et vous serez heureux lorsque vous aurez la liberté de changer vos implémentations (cachées derrière l'interface) sans casser le code de votre équipe. C'est une variante de la dissimulation d'informations (les interfaces sont publiques, les implémentations sont cachées aux programmeurs clients). En savoir plus sur les variantes protégées .

Consultez également cette question connexe sur le codage d'une interface .


1

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

  1. Utilisation en comportement polymorphe. Où vous souhaitez 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 là où cela est nécessaire, comme l'utilisation la plus courante est avec des objets COM, où une classe 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. Pour réduire l'utilisation de la mémoire en chargeant des méthodes spécifiques dans une classe. Comme si vous avez trois objets 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(string name ,string fname);

}

// Same for IOrder and IOrderItem
//


public class  BusinessLayer: IUser, IOrder, IOrderItem

{    
    public void AddUser(string name ,string fname)
    {
        // Do stuffs here.
    }

    // All methods from all interfaces must be implemented.

}

Si vous souhaitez uniquement ajouter un utilisateur, procédez comme suit:

IUser user = new (IUser)BusinessLayer();

// It will load  all methods into memory which are declared in the IUser interface.

user.AddUser();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.