Quand utiliser une interface au lieu d'une classe abstraite et vice versa?


427

Cela peut être une question générique de POO. Je voulais faire une comparaison générique entre une interface et une classe abstraite sur la base de leur utilisation.

Quand voudrait-on utiliser une interface et quand voudrait-on utiliser une classe abstraite ?



1
En plus des réponses ci-dessous, voici
Anthony

utilisez l'abstrait lorsque vous n'êtes pas sûr de ce que la classe va faire. utilisez l'interface si vous l'êtes.
Uğur Gümüşhan

Je suis intéressé de voir combien de développeurs, qui ne travaillent pas chez Microsoft, définissent et utilisent des interfaces dans leur développement quotidien.
user1451111

Réponses:


432

J'ai écrit un article à ce sujet:

Classes abstraites et interfaces

Résumant:

Lorsque nous parlons de classes abstraites, nous définissons les caractéristiques d'un type d'objet; spécifiant ce qu'est un objet .

Lorsque nous parlons d'une interface et définissons des capacités que nous promettons de fournir, nous parlons d'établir un contrat sur ce que l'objet peut faire.


114
Cela a été rès utile: Interfaces do not express something like "a Doberman is a type of dog and every dog can walk" but more like "this thing can walk". Merci
aexl

2
Il semble que votre lien soit mort.
Kim Ahlstrøm Meyn Mathiassen

L'explication d'Alex ci-dessous, concernant la différence entre décrire uniquement les fonctions implémentées et décrire également l'état stocké, semble être une meilleure réponse à cette question, car les différences ne sont pas seulement philosophiques.
Duncan Malashock

1
Duncan Malashock, pas vraiment. La réponse de Jorge est la meilleure. La réponse d'Alex se concentre sur la mécanique, tandis que Jorge est plus sur la sémantique.
Nazar Merza

8
J'aime la déclaration avant votre réponse spécifiée:Use abstract classes and inheritance if you can make the statement “A is a B”. Use interfaces if you can make the statement “A is capable of [doing] as”
S1r-Lanzelot

433

Une classe abstraite peut avoir un état ou une fonctionnalité partagée. Une interface n'est qu'une promesse de fournir l'état ou la fonctionnalité. Une bonne classe abstraite réduira la quantité de code qui doit être réécrite car sa fonctionnalité ou son état peuvent être partagés. L'interface n'a aucune information définie à partager


65
Pour moi, c'est la meilleure réponse ici et c'est dommage qu'il n'ait pas été voté plus haut. Oui, il existe des différences philosophiques entre les deux concepts, mais le point racine est que les classes abstraites garantissent que tous les descendants partagent la fonctionnalité / l'état, où une interface ne garantit qu'un lien commun.
drharris

3
Par exemple, une classe de base abstraite est utilisée pour le modèle de conception de méthode de modèle, tandis qu'une interface est utilisée pour le modèle de conception de stratégie .
Raedwald

1
Je pense que le résumé de Jorge explique le principal mais derrière l'existence pour les deux, tandis que la réponse d'Alex est la différence de résultats. J'aimerais pouvoir marquer les deux comme les bonnes réponses, mais je préfère toujours la réponse de Jorge.
Chirantan

Et ici est par exemple avec le code.
shaijut

Pour moi, ceci "Une bonne classe abstraite réduira la quantité de code qui doit être réécrite parce que sa fonctionnalité ou son état peut être partagé." déclaration est au cœur de la réponse.
Div Tiwari

82

Personnellement, je n'ai presque jamais besoin d'écrire des cours abstraits.

La plupart du temps, je vois des classes abstraites être (mal) utilisées, c'est parce que l'auteur de la classe abstraite utilise le modèle "Méthode de modèle".

Le problème avec la "méthode Template" est qu'elle est presque toujours rentrante - la classe "dérivée" connaît non seulement la méthode "abstraite" de sa classe de base qu'elle implémente, mais aussi les méthodes publiques de la classe de base , même si la plupart du temps il n'a pas besoin de les appeler.

Exemple (trop simplifié):

abstract class QuickSorter
{
    public void Sort(object[] items)
    {
        // implementation code that somewhere along the way calls:
        bool less = compare(x,y);
        // ... more implementation code
    }
    abstract bool compare(object lhs, object rhs);
}

Donc, ici, l'auteur de cette classe a écrit un algorithme générique et a l'intention que les gens l'utilisent en le "spécialisant" en fournissant leurs propres "hooks" - dans ce cas, une méthode "compare".

Donc, l'utilisation prévue est quelque chose comme ceci:

class NameSorter : QuickSorter
{
    public bool compare(object lhs, object rhs)
    {
        // etc.
    }
}

Le problème est que vous avez indûment couplé deux concepts:

  1. Une façon de comparer deux articles (quel article doit aller en premier)
  2. Une méthode de tri des éléments (par exemple tri rapide vs tri par fusion, etc.)

Dans le code ci-dessus, théoriquement, l'auteur de la méthode "compare" peut rappeler de manière réentrante dans la méthode "Sort" de la superclasse ... même si en pratique ils ne voudront ou n'auront jamais besoin de le faire.

Le prix que vous payez pour ce couplage inutile est qu'il est difficile de changer la superclasse, et dans la plupart des langues OO, impossible de la changer au moment de l'exécution.

La méthode alternative consiste à utiliser le modèle de conception "Stratégie" à la place:

interface IComparator
{
    bool compare(object lhs, object rhs);
}

class QuickSorter
{
    private readonly IComparator comparator;
    public QuickSorter(IComparator comparator)
    {
        this.comparator = comparator;
    }

    public void Sort(object[] items)
    {
        // usual code but call comparator.Compare();
    }
}

class NameComparator : IComparator
{
    bool compare(object lhs, object rhs)
    {
        // same code as before;
    }
}

Alors remarquez maintenant: tout ce que nous avons, ce sont des interfaces et des implémentations concrètes de ces interfaces. En pratique, vous n'avez pas vraiment besoin d'autre chose pour faire une conception OO de haut niveau.

Pour "masquer" le fait que nous avons implémenté le "tri des noms" en utilisant une classe "QuickSort" et un "NameComparator", nous pourrions encore écrire une méthode d'usine quelque part:

ISorter CreateNameSorter()
{
    return new QuickSorter(new NameComparator());
}

Chaque fois que vous avez une classe abstraite, vous pouvez le faire ... même lorsqu'il existe une relation de ré-entrée naturelle entre la classe de base et la classe dérivée, il est généralement avantageux de les rendre explicites.

Une dernière pensée: tout ce que nous avons fait ci-dessus est de "composer" une fonction "NameSorting" en utilisant une fonction "QuickSort" et une fonction "NameComparison" ... dans un langage de programmation fonctionnel, ce style de programmation devient encore plus naturel, avec moins de code.


5
Ce n'est pas parce que vous pouvez utiliser des classes abstraites ou un modèle de méthode de modèle que vous devez les éviter. Le modèle de stratégie est un modèle différent pour une situation différente comme dans cet exemple, mais il existe de nombreux exemples où un modèle de modèle est beaucoup plus approprié que la stratégie.
Jorge Córdoba

5
Eh bien, d'après mon expérience, je ne les rencontre jamais (situations où la méthode des modèles est préférable) ... ou rarement de toute façon. Et c'est tout "abstrait" est - la prise en charge de la langue pour le modèle de conception "méthode de modèle".
Paul Hollingsworth

Ok, je l'ai utilisé une fois pour un système expert où le processus ressemblait à quelque chose, obtenez 1. FillTheParameters, 2. Créez le produit vectoriel entre eux, 3. Pour chaque paire, calculez le résultat, 4. Joignez les résultats, où les étapes 1 et 3 où délégué et 2 et 4 mis en œuvre dans la classe de base.
Jorge Córdoba

10
Je trouve presque toute utilisation des classes abstraites plus difficile à comprendre. Penser en termes de boîtes qui communiquent entre elles au lieu de relations d'héritage est plus facile (pour moi) ... Mais je conviens également que les langages OO actuels forcent trop de passe-partout ... Le fonctionnel sera le moyen de passer en revue OO
Paul Hollingsworth

4
L'exemple d'abus est assez banal. Cela se résume rarement à de si belles fonctionnalités dépouillées comme comparer. Les situations où il existe des fonctionnalités par défaut que les classes dérivées remplacent ou étendent sont beaucoup plus courantes (et dans ce dernier cas, il est parfaitement valide d'appeler la fonction de classe de base). Dans votre exemple, il n'y a pas de fonctionnalité par défaut, donc l'utilisation de la classe abstraite n'a aucune justification.
SomeWittyUsername

41

Si vous regardez Java comme langage OOP,

"L' interface ne fournit pas d'implémentation de méthode " n'est plus valide avec le lancement de Java 8. Maintenant, java fournit une implémentation dans l'interface pour les méthodes par défaut.

En termes simples, je voudrais utiliser

interface: pour mettre en œuvre un contrat par plusieurs objets indépendants. Il offre lacapacité" A A ".

classe abstraite: pour implémenter un comportement identique ou différent parmi plusieurs objets associés. Il établit une relation" EST A ".

Le site Web Oracle fournit les principales différences entre interfaceet la abstractclasse.

Envisagez d'utiliser des classes abstraites si:

  1. Vous souhaitez partager du code entre plusieurs classes étroitement liées.
  2. Vous vous attendez à ce que les classes qui étendent votre classe abstraite aient de nombreuses méthodes ou champs communs, ou nécessitent des modificateurs d'accès autres que publics (tels que protégés et privés).
  3. Vous souhaitez déclarer des champs non statiques ou non définitifs.

Envisagez d'utiliser des interfaces si:

  1. Vous vous attendez à ce que des classes indépendantes implémentent votre interface. Par exemple, de nombreux objets non liés peuvent implémenter une Serializableinterface.
  2. Vous souhaitez spécifier le comportement d'un type de données particulier, mais ne vous souciez pas de savoir qui implémente son comportement.
  3. Vous souhaitez profiter de l'héritage multiple de type.

Exemple:

Classe abstraite ( est une relation)

Reader est une classe abstraite.

BufferedReader est unReader

FileReader est unReader

FileReaderet BufferedReadersont utilisés dans un but commun: lire des données, et ils sont liés à travers la Readerclasse.

Interface ( capacité A A )

Serializable est une interface.

Supposons que vous avez deux classes dans votre application, qui implémentent une Serializableinterface

Employee implements Serializable

Game implements Serializable

Ici, vous ne pouvez pas établir de relation via l' Serializableinterface entre Employeeet Game, qui sont destinés à des fins différentes. Les deux sont capables de sérialiser l'état et la comparaison s'arrête là.

Jetez un œil à ces articles:

Comment aurais-je dû expliquer la différence entre une interface et une classe abstraite?


40

D'accord, juste après avoir "grokké" cela - ici c'est en termes profanes (n'hésitez pas à me corriger si je me trompe) - je sais que ce sujet est oooooold, mais quelqu'un d'autre pourrait tomber dessus un jour ...

Les classes abstraites vous permettent de créer un plan directeur et vous permettent en outre de CONSTRUIRE (implémenter) les propriétés et les méthodes que vous souhaitez que TOUS ses descendants possèdent.

Une interface, d'autre part, vous permet uniquement de déclarer que vous souhaitez que des propriétés et / ou des méthodes avec un nom donné existent dans toutes les classes qui l'implémentent - mais ne spécifie pas comment vous devez l'implémenter. En outre, une classe peut implémenter de NOMBREUSES interfaces, mais ne peut étendre qu'une seule classe abstraite. Une interface est plus un outil architectural de haut niveau (qui devient plus clair si vous commencez à saisir les modèles de conception) - un résumé a un pied dans les deux camps et peut également effectuer une partie du sale boulot.

Pourquoi utiliser l'un sur l'autre? Le premier permet une définition plus concrète des descendants - le second permet un plus grand polymorphisme . Ce dernier point est important pour l'utilisateur final / codeur, qui peut utiliser ces informations pour implémenter l'AP I (nterface) dans une variété de combinaisons / formes pour répondre à leurs besoins.

Je pense que ce fut le moment de "l'ampoule" pour moi - pensez aux interfaces moins du point de vue de l'auteur et plus de celui de tout codeur venant plus tard dans la chaîne qui ajoute une implémentation à un projet ou étend une API.


pour construire sur ceci: Un objet qui implémente une interface prend son TYPE. C'est crucial. Ainsi, vous pouvez transmettre différentes variantes de l'interface à une classe, mais vous y référer (et leurs méthodes) AVEC LE NOM DE TYPE DE L'INTERFACE. Ainsi, vous éliminez le besoin d'un commutateur ou d'une boucle if / else. Essayez ce didacticiel sur le sujet - il montre l'utilisation d'une interface via le modèle de stratégie. phpfreaks.com/tutorial/design-patterns---strategy-and-bridge/…
sunwukung

Je suis totalement d'accord sur votre moment d'ampoule: "API (nterface) dans une variété de combinaisons / formes pour répondre à leurs besoins"! Très très bon point à souligner.
Trevor Boyd Smith

39

Mes deux centimes:

Une interface définit fondamentalement un contrat auquel toute classe d'implémentation doit adhérer (implémenter les membres de l'interface). Il ne contient aucun code.

D'un autre côté, une classe abstraite peut contenir du code, et il peut y avoir certaines méthodes marquées comme abstraites qu'une classe héritée doit implémenter.

Les rares situations dans lesquelles j'ai utilisé des classes abstraites sont lorsque j'ai des fonctionnalités par défaut que la classe héritière peut ne pas être intéressante pour remplacer, par exemple une classe de base abstraite, dont héritent certaines classes spécialisées.

Exemple (un très rudimentaire!): Considérons une classe de base appelée client qui a des méthodes abstraites comme CalculatePayment(), CalculateRewardPoints()et certaines méthodes non abstraites comme GetName(), SavePaymentDetails().

Les classes spécialisées aiment RegularCustomer et GoldCustomerhériteront de la Customerclasse de base et implémenteront leur propre logique de méthode CalculatePayment()et CalculateRewardPoints(), mais réutilisent les méthodes GetName()et SavePaymentDetails().

Vous pouvez ajouter plus de fonctionnalités à une classe abstraite (c'est-à-dire des méthodes non abstraites) sans affecter les classes enfants qui utilisaient une ancienne version. Alors que l'ajout de méthodes à une interface affecterait toutes les classes qui l'implémentent, car elles devraient désormais implémenter les nouveaux membres de l'interface.

Une classe abstraite avec tous les membres abstraits serait similaire à une interface.


1
+1 pour "Vous pouvez ajouter plus de fonctionnalités à une classe abstraite (méthodes non abstraites, c'est-à-dire) sans affecter les classes enfants qui utilisaient une ancienne version. Alors que l'ajout de méthodes à une interface affecterait toutes les classes qui l'implémentent, comme elles devraient désormais l'implémenter les nouveaux membres de l'interface ajoutés. "
Div Tiwari

les interfaces peuvent avoir des méthodes "par défaut" donc ne pas avoir d'impl de méthode dans les interfaces est une mauvaise idée. La relation IS-A "parent-enfant" est la clé ici. Aussi, "Attributs partagés" vs "Propriétés partagées". par exemple Chien iS-A Animal. Mais un chien peut aussi "marcher"
ha9u63ar

30

Quand faire ce qui est très simple si le concept est clair dans votre esprit.

Les classes abstraites peuvent être dérivées tandis que les interfaces peuvent être implémentées. Il y a une différence entre les deux. Lorsque vous dérivez une classe abstraite, la relation entre la classe dérivée et la classe de base est une relation «est une». Par exemple, un chien est un animal, un mouton est un animal, ce qui signifie qu'une classe dérivée hérite de certaines propriétés de la classe de base.

Alors que pour l'implémentation des interfaces, la relation est "peut être". par exemple, un chien peut être un chien espion. Un chien peut être un chien de cirque. Un chien peut être un chien de course. Ce qui signifie que vous implémentez certaines méthodes pour acquérir quelque chose.

J'espère que je suis clair.


11

1.Si vous créez quelque chose qui fournit des fonctionnalités communes à des classes indépendantes, utilisez une interface.

2.Si vous créez quelque chose pour des objets qui sont étroitement liés dans une hiérarchie, utilisez une classe abstraite.



7

Je pense que la façon la plus succincte de le dire est la suivante:

Propriétés partagées => classe abstraite.
Fonctionnalité partagée => interface.

Et pour le dire moins succinctement ...

Exemple de classe abstraite:

public abstract class BaseAnimal
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }
}

public class Dog : BaseAnimal
{
    public Dog() : base(4) { }
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }
}

Puisque les animaux ont une propriété partagée - nombre de pattes dans ce cas - il est logique de créer une classe abstraite contenant cette propriété partagée. Cela nous permet également d'écrire du code commun qui fonctionne sur cette propriété. Par exemple:

public static int CountAllLegs(List<BaseAnimal> animals)
{
    int legCount = 0;
    foreach (BaseAnimal animal in animals)
    {
        legCount += animal.NumberOfLegs;
    }
    return legCount;
}

Exemple d'interface:

public interface IMakeSound
{
    void MakeSound();
}

public class Car : IMakeSound
{
    public void MakeSound() => Console.WriteLine("Vroom!");
}

public class Vuvuzela : IMakeSound
{
    public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");        
}

Notez ici que Vuvuzelas et Cars sont des choses complètement différentes, mais ils ont des fonctionnalités partagées: faire du son. Ainsi, une interface est logique ici. De plus, cela permettra aux programmeurs de regrouper des choses qui produisent des sons ensemble sous une interface commune - IMakeSounddans ce cas. Avec cette conception, vous pouvez écrire le code suivant:

List<IMakeSound> soundMakers = new List<ImakeSound>();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());

foreach (IMakeSound soundMaker in soundMakers)
{
    soundMaker.MakeSound();
}

Pouvez-vous dire ce que cela produirait?

Enfin, vous pouvez combiner les deux.

Exemple combiné:

public interface IMakeSound
{
    void MakeSound();
}

public abstract class BaseAnimal : IMakeSound
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }

    public abstract void MakeSound();
}

public class Cat : BaseAnimal
{
    public Cat() : base(4) { }

    public override void MakeSound() => Console.WriteLine("Meow!");
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }

    public override void MakeSound() => Console.WriteLine("Hello, world!");
}

Ici, nous demandons à tous de BaseAnimalfaire un son, mais nous ne connaissons pas encore sa mise en œuvre. Dans un tel cas, nous pouvons résumer l'implémentation de l'interface et déléguer son implémentation à ses sous-classes.

Un dernier point, rappelez-vous comment dans l'exemple de classe abstraite, nous avons pu opérer sur les propriétés partagées de différents objets et dans l'exemple d'interface, nous avons pu invoquer la fonctionnalité partagée de différents objets? Dans ce dernier exemple, nous pourrions faire les deux.


7

Quand préférer une classe abstraite à une interface?

  1. Si l'on prévoit de mettre à jour une classe de base tout au long de la vie d'un programme / projet, il est préférable de permettre que la classe de base soit une classe abstraite
  2. Si l'on essaie de construire une épine dorsale pour des objets qui sont étroitement liés dans une hiérarchie, il est très avantageux d'utiliser une classe abstraite

Quand préférer une interface à une classe abstraite?

  1. Si l'on n'a pas affaire à un cadre hiérarchique massif, les interfaces seraient un excellent choix
  2. Étant donné que l'héritage multiple n'est pas pris en charge avec les classes abstraites (problème de diamant), les interfaces peuvent sauver la journée

Qu'est-ce qui vous a fait penser qu'une question vieille de près d'une décennie avait besoin d'une 22e réponse?
jonrsharpe

3
Le même type de réflexion qui m'a fait chercher une réponse simple à la question.
Satya

1
FWIW, j'aime vraiment cette réponse.
Brent Rittenhouse

6

Les classes peuvent hériter d'une seule classe de base, donc si vous souhaitez utiliser des classes abstraites pour fournir un polymorphisme à un groupe de classes, elles doivent toutes hériter de cette classe. Les classes abstraites peuvent également fournir des membres qui ont déjà été implémentés. Par conséquent, vous pouvez garantir une certaine quantité de fonctionnalités identiques avec une classe abstraite, mais pas avec une interface.

Voici quelques recommandations pour vous aider à décider d'utiliser une interface ou une classe abstraite pour fournir le polymorphisme à vos composants.

  • Si vous prévoyez de créer plusieurs versions de votre composant, créez une classe abstraite. Les classes abstraites fournissent un moyen simple et facile de versionner vos composants. En mettant à jour la classe de base, toutes les classes héritées sont automatiquement mises à jour avec la modification. Les interfaces, en revanche, ne peuvent pas être modifiées une fois créées de cette manière. Si une nouvelle version d'une interface est requise, vous devez créer une toute nouvelle interface.
  • Si la fonctionnalité que vous créez sera utile sur un large éventail d'objets disparates, utilisez une interface. Les classes abstraites doivent être utilisées principalement pour les objets qui sont étroitement liés, tandis que les interfaces sont les mieux adaptées pour fournir des fonctionnalités communes à des classes non liées.
  • Si vous concevez de petites fonctionnalités concises, utilisez des interfaces. Si vous concevez de grandes unités fonctionnelles, utilisez une classe abstraite.
  • Si vous souhaitez fournir des fonctionnalités communes et implémentées parmi toutes les implémentations de votre composant, utilisez une classe abstraite. Les classes abstraites vous permettent d'implémenter partiellement votre classe, tandis que les interfaces ne contiennent aucune implémentation pour les membres.

Copié depuis:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx


Il n'y a rien dans UML qui empêche l'héritage de plusieurs classes. L'héritage multiple est déterminé par un langage de programmation et non par UML. Par exemple, l'héritage de plusieurs classes n'est pas autorisé en Java et C #, car il est autorisé en C ++.
BobRodes

@BobRodes: Il existe un certain nombre de fonctionnalités que les frameworks orientés objet peuvent fournir dans diverses combinaisons, mais pas dans toutes les combinaisons. L'héritage multiple généralisé exclut certaines autres combinaisons utiles de fonctionnalités, notamment la possibilité de caster une référence directement vers n'importe quel type parent de l'instance réelle ou tout type d'interface pris en charge ainsi que la possibilité de compiler indépendamment les types de base et les types dérivés et de les joindre au moment de l'exécution.
supercat

@supercat Yours est une bonne explication de certains des problèmes qui résultent de l'utilisation de l'héritage multiple. Néanmoins, rien dans UML n'empêche l'héritage de plusieurs classes dans un diagramme. Je répondais à ce qui précède "Les classes peuvent hériter d'une seule classe de base ...", ce qui n'est pas tout à fait le cas.
BobRodes

@BobRodes: La question a été taguée Java. Java inclut les fonctionnalités indiquées, et est donc limité aux formes d'héritage multiple qui ne peuvent pas produire un "diamant mortel" (bien qu'en fait la façon dont ils ont implémenté les implémentations d'interface par défaut rend le diamant mortel possible).
supercat

@supercat Oh, d'accord. Je ne regarde généralement pas les balises java, donc au moment où j'ai écrit que je pensais au moins que je commentais une réponse UML. En tout cas, je suis d'accord avec votre commentaire.
BobRodes

3

Envisagez d'utiliser des classes abstraites si l'une de ces déclarations s'applique à votre situation:

  1. Vous souhaitez partager du code entre plusieurs classes étroitement liées.
  2. Vous vous attendez à ce que les classes qui étendent votre classe abstraite aient de nombreuses méthodes ou champs communs ou nécessitent des modificateurs d'accès autres que publics (tels que protégés et privés).
  3. Vous souhaitez déclarer des champs non statiques ou non définitifs. Cela vous permet de définir des méthodes qui peuvent accéder et modifier l'état de l'objet auquel elles appartiennent.

Envisagez d'utiliser des interfaces si l'une de ces déclarations s'applique à votre situation:

  1. Vous vous attendez à ce que des classes indépendantes implémentent votre interface. Par exemple, les interfaces Comparable et Cloneable sont implémentées par de nombreuses classes non liées.
  2. Vous souhaitez spécifier le comportement d'un type de données particulier, mais ne vous souciez pas de savoir qui implémente son comportement.
  3. Vous souhaitez profiter de plusieurs héritages.

La source


2

Les réponses varient selon les langues. Par exemple, en Java, une classe peut implémenter (hériter de) plusieurs interfaces mais hériter uniquement d'une classe abstraite. Les interfaces vous offrent donc plus de flexibilité. Mais ce n'est pas vrai en C ++.


2

Pour moi, j'irais avec des interfaces dans de nombreux cas. Mais je préfère les classes abstraites dans certains cas.

Les classes en OO se réfèrent généralement à l'implémentation. J'utilise des classes abstraites lorsque je veux forcer certains détails d'implémentation aux enfants, sinon je vais avec des interfaces.

Bien sûr, les classes abstraites sont utiles non seulement pour forcer l'implémentation mais aussi pour partager certains détails spécifiques entre de nombreuses classes liées.


1

Utilisez une classe abstraite si vous souhaitez fournir des implémentations de base.


1
Merci Sebastian. Mais que faire si je n'ai pas besoin d'une implémentation de base? Une classe abstraite et une interface ne seront-elles pas les mêmes alors si c'est la seule différence entre elles? Pourquoi y a-t-il une différence?
Chirantan

1
Parce que certains langages n'ont pas d'interfaces - C ++.
jmucchiello

1

en java, vous pouvez hériter d'une classe (abstraite) pour "fournir" des fonctionnalités et vous pouvez implémenter de nombreuses interfaces pour "assurer" des fonctionnalités


petit conseil: si vous voulez hériter d'une classe abstraite et d'une interface, assurez-vous que la classe abstraite implémente l'interface
Andreas Niedermair

1

Purement sur la base de l'héritage, vous utiliseriez un résumé où vous définissez clairement des relations abstraites descendantes (c.-à-d. Animal-> chat) et / ou nécessitez l'héritage de propriétés virtuelles ou non publiques, en particulier l'état partagé (que les interfaces ne peuvent pas prendre en charge ).

Vous devriez essayer de privilégier la composition (via l'injection de dépendances) plutôt que l'héritage là où vous le pouvez, et notez que les interfaces étant des contrats prennent en charge les tests unitaires, la séparation des préoccupations et l'héritage multiple (variable selon la langue) d'une manière que les résumés ne peuvent pas.


1

Un endroit intéressant où les interfaces s'en sortent mieux que les classes abstraites est lorsque vous devez ajouter des fonctionnalités supplémentaires à un groupe d'objets (liés ou non). Si vous ne pouvez pas leur donner une classe abstraite de base (par exemple, ils sont sealedou ont déjà un parent), vous pouvez leur donner une interface factice (vide) à la place, puis simplement écrire des méthodes d'extension pour cette interface.


0

Cela peut être un appel très difficile à faire ...

Un pointeur que je peux donner: un objet peut implémenter de nombreuses interfaces, tandis qu'un objet ne peut hériter que d'une classe de base (dans un langage OO moderne comme c #, je sais que C ++ a plusieurs héritages - mais n'est-ce pas mal vu?)


L'héritage multiple permet à Mixin d'être implémenté de manière apparente, des Mixin bien écrits sont un jeu d'enfant, mais très difficiles à trouver et difficiles à écrire sans échouer quelque part. Les mixin sont plutôt sympas dans leur ensemble bien que l'OMI.
Martijn Laarman

En fait, je ne l'ai pas fait, l'héritage multiple est en effet un déclencheur de débat sûr entre nous, geeks, je ne vois absolument aucune raison de voter contre. En fait, j'ai voté pour votre réponse.
Martijn Laarman le

Le seul point que j'ai essayé de faire est que des façons de mélanger dans des langages à héritage unique sont également possibles (C #, PHP, javascript) mais à travers un comportement hacky ou une syntaxe collante. J'adore Mixin quand ils travaillent, mais je ne suis toujours pas décisif sur l'héritage multiple ou non.
Martijn Laarman le

Cette réponse est plus une différence syntaxique qu'une différence de conception. Je pense qu'il demande une différence de conception
Pramod Setlur

0

Une classe abstraite peut avoir des implémentations.

Une interface n'a pas d'implémentations, elle définit simplement une sorte de contrat.

Il peut également y avoir des différences dépendantes du langage: par exemple, C # n'a pas d'héritage multiple, mais plusieurs interfaces peuvent être implémentées dans une classe.


Quand vous dites «une sorte de contrat», voulez-vous dire comme dans les services Web?
Chirantan

Techniquement parlant, les services Web ne fonctionnent pas avec les interfaces. Par contrat, je veux dire que l'utilisateur d'un objet sait quelles méthodes sont présentes sur cet objet. Par exemple, une interface IMouse aura une méthode Move et un événement de bouton gauche et droit de la souris.
Gerrie Schenck

-1

La règle de base est la suivante: pour les "noms", utilisez la classe abstraite et pour les "verbes", utilisez l'interface

Par exemple: carest une classe abstraite et drive, nous pouvons en faire une interface.


5
Cela n'a pas de sens, nous pouvons également mettre la fonctionnalité de drivedans la voiture - c'est une classe abstraite.
Arslan Ali
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.