web-dev-qa-db-fra.com

Comment saurai-je quand créer une interface?

J'en suis à un stade de mon apprentissage du développement où je sens que je dois en savoir plus sur les interfaces.

Je les lis souvent, 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 simplement 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. Merci.

189
user53885

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<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.

146
Jimmy

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 able. 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, vous la tapez comme IWalkable et vous pouvez mettre tous les animaux qui marchent ainsi que les robots dans la liste.

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.

129
rmeador

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.

70
Element

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 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 fiche de comment ils courent et marchent, tant qu'ils courent et marchent. Mon RunThenWalk sera valable tant qu'ils respectent cet accord. Il fonctionne parfaitement bien sans rien savoir de la classe. "

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

32
Larsenal

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. Supposons maintenant que vous devez parcourir tous ces objets et appeler leur méthode Drive(). 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()
18
Spencer Ruport

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 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 le soin aux développeurs de 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 qu'elles peuvent le faire en parallèle.

16
Karl

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

Le sergent ne se soucie pas si vous êtes un développeur de logiciels, musicien ou avocat.
Vous êtes traité comme 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,
traitez tout le monde comme des abstractions de soldats (... et punissez-les lorsqu'ils ne se comportent pas comme des soldats).

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.

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.

15
Arnis Lapsa

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 de 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.

14
tvanfosson

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

Il y a une interface entre les appareils électriques et le réseau électrique - c'est le ensemble de conventions sur 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 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 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 mettre à nivea trains sans réarchitecturer 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 les interactions et comment 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.

10
user8599

Un exemple de code (combinaison d'Andrew avec un extra de moi à quel 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.

5
eglasius

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 toujours complètes.

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
Yes - that Jake.

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 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 parce que le contrôle personnalisé gère tout cela.

4
Austin Salonen

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, de manger, de 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 méthode 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, 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++.

4
Epitaph

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

Modéliser avant les interfaces

enter image description here

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 iterface enter image description here

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();
    }
}
3
Marcin Szymczak

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 auxquels un concepteur visuel est associé implémentent IComponent afin que le IDE 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 ne saviez pas qu'elles existaient. Cela est particulièrement important lorsque des espaces de noms mis à jour ou nouveaux sont ajoutés au .NET Framework.

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
Jobo

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 ces méthodes appelle 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. Puisque tout ce à quoi vous êtes lié est votre interface (contrat), vous pouvez échanger celle que votre application utilise sans changer le code qui la consomme.

2
Jab

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 Gun qui définit une fonction shoot().

Nous avons besoin de différentes sous-classes de la classe Gun à savoir ShotGunSniper 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 tous les pistolets dans son armure. Permet de créer un List pour 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 appeler simplement la fonction shoot(), lorsque fire() est appelée.

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

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

Conclusion

Créez une interface, lorsqu'une fonction de classe dépend de ne 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 fonction fire() de la classe Shooter attend des pistolets (Sniper, ShotGun) qu'ils implémentent la fonction shoot(). Donc, si nous passons le pistolet et tirons.

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

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

2
Sorter

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. Elle 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
Powerlord

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
Ryan Thames

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
Matthew Brubaker

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 quand je refactorise une méthode qui soudainement doit 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
Sylvain Rodrigue

Les interfaces deviendront évidentes lorsque vous devenez un développeur de bibliothèque (quelqu'un qui code pour d'autres codeurs). La plupart d'entre nous commencent par 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 rendre certaines parties de votre code stables . Cela est particulièrement utile lorsqu'il s'agit d'un projet - é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 dans une é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 l'information se cache (les interfaces sont publiques, les implémentations sont cachées aux programmeurs clients). En savoir plus sur variations protégées .

Voir aussi ceci question connexe sur le codage d'une interface .

1
Fuhrmanator

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 un DLL qui hérite de l'interface; ces méthodes sont appelés dans les coulisses, et vous avez juste besoin de les implémenter mais avec la même structure que celle définie dans COM DLL que vous ne pouvez connaître que via l'interface qu'ils 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();
1
sajid khan