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

il s'agit peut-être d'une question générique. Je voulais faire un générique de comparaison entre une interface et une classe abstraite sur la base de leur utilisation.

Quand on veut utiliser une interface et quand on veut utiliser une classe abstraite ?

362
demandé sur Ravindra babu 2009-01-26 11:47:38

21 réponses

j'ai écrit un article à ce sujet:

les classes Abstraites et les interfaces

Résumant:

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

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

360
répondu Jorge Córdoba 2017-08-21 19:34:30

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 parce que sa fonctionnalité ou son état peuvent être partagés. L'interface n'a aucune information définie à partager

386
répondu Alex 2009-01-26 08:52:47

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

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

le problème avec la "méthode de modèle" est qu'il est presque toujours quelque peu entrant-la classe "dérivé" connaît non seulement la méthode" abstraite " de sa classe de base qu'il met en œuvre, mais aussi sur les méthodes publiques de la classe de base, même si la plupart du temps il n'a pas besoin de les appeler.

(trop simplifié) exemple:

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 entend que les gens l'utilisent en le" spécialisant "en fournissant leurs propres" crochets "- dans ce cas, une méthode" comparer".

donc l'usage prévu est quelque chose comme ceci:

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

le problème avec ceci est que vous avez exagérément couplé deux concepts:

  1. Un moyen de comparaison de deux éléments (ce point doit passer en premier)
  2. méthode de tri des articles (c.-à-d. quicksort vs merge sort etc.)

dans le code ci-dessus, théoriquement, l'auteur de la méthode" comparer "peut re-entrantly rappeler dans la superclasse" Tri " méthode... même si dans la pratique ils ne seront jamais envie ou besoin de ce faire.

le prix à payer pour ce couplage inutile est qu'il est difficile de changer la superclasse, et dans la plupart des langues OO, impossible de la changer à 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;
    }
}

donc notez maintenant: tout ce que nous avons, ce sont des interfaces, et des implémentations concrètes de ces interfaces. Dans la pratique, vous n'avez pas vraiment besoin de quoi que ce soit d'autre pour faire une OO de haut niveau conception.

pour "cacher" le fait que nous avons mis en œuvre 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());
}

Tout le temps, vous avez une classe abstraite, vous pouvez le faire... même s'il existe une relation 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 "composer" une fonction "NameSorting" en utilisant une fonction "QuickSort" et une fonction "NameComparison"... dans un langage de programmation fonctionnel, ce style de programmation est encore plus naturel, avec moins de code.

75
répondu Paul Hollingsworth 2009-12-17 23:42:56

OK, ayant juste "grokked" cela moi - même-ici, il 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 à travers elle un jour...

les classes abstraites vous permettent de créer un plan, et vous permettent de construire (mettre en œuvre) en plus des propriétés et des méthodes que vous voulez que tous ses descendants possèdent.

Une interface d'autre part permet uniquement de déclarer que vous vous voulez que les propriétés et / ou les méthodes avec un nom donné existent dans toutes les classes qui l'implémentent - mais ne spécifie pas comment vous devriez l'implémenter. En outre, une classe peut implémenter de nombreuses interfaces, mais ne peut étendre qu'une 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 Abstrait a un pied dans les deux camps et peut effectuer une partie du sale travail aussi.

Pourquoi utiliser l'un sur l'autre? L'ancien permet une plus concrète définition des descendants - cette dernière permet une plus grande polymorphisme . Ce dernier point est important pour l'utilisateur final / codeur, qui peut utiliser cette information pour mettre en œuvre L'A. P. I(nterface) dans une variété de combinaisons/formes pour répondre à leurs besoins.

je pense que c'était le moment" de l'ampoule " pour moi-penser aux interfaces moins à partir de la perspective de l'auteur et plus de celui de n'importe quel codeur venant plus tard dans la chaîne qui ajoute la mise en œuvre à un projet, ou prolongeant une API.

38
répondu sunwukung 2011-04-07 12:10:57

mes deux cents:

une interface définit essentiellement un contrat, que toute classe d'implémentation doit respecter(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 des méthodes identifiées comme abstraites qu'une classe héritière doit implémenter.

les rares situations où j'ai utilisé des classes abstraites, c'est quand j'ai un défaut fonctionnalité que la classe héritante pourrait ne pas être intéressante en surpassant, par exemple une classe de base abstraite, dont certaines classes spécialisées héritent.

Exemple(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() .

classes spécialisées comme RegularCustomer et GoldCustomer hériteront de la Customer classe de base et mettre en œuvre leur propre logique de méthode CalculatePayment() et CalculateRewardPoints() , mais réutiliser les méthodes GetName() et SavePaymentDetails() .

vous pouvez ajouter plus de fonctionnalité à une classe abstraite(méthodes non abstraites qui est) sans affecter les classes d'enfants qui utilisaient une version plus ancienne. Alors que l'ajout de méthodes à une interface affecterait toutes les classes l'implémentant puisqu'elles devraient maintenant implémenter les nouveaux membres d'interface ajoutés.

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

33
répondu PreethaA 2018-04-24 17:14:57

Quand le faire est une chose très simple si vous avez le concept clair dans votre esprit.

Les classes abstraites

peuvent être dérivées alors que les Interfaces peuvent être implémentées. Il y a une certaine 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 'est une' relation. par exemple, un Chien est un Animal, un Mouton est un Animal qui signifie qu'une classe Dérivée hérite des propriétés de la classe de base.

alors que pour la mise en œuvre des interfaces, la relation est "peut être". par exemple, un Chien peut être un espion chien. Un chien peut être un chien de cirque. Un chien peut être un chien de course. Ce qui signifie que vous mettez en œuvre certaines méthodes pour acquérir quelque chose.

j'espère que je suis clair.

28
répondu Aamir 2009-01-26 10:41:12

Si vous êtes à la recherche à java comme langage de programmation orientée objet,

" interface ne fournit pas l'implémentation de la méthode " n'est plus valide avec le lancement de Java 8. Maintenant, java fournit l'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 multiple objets indépendants. Il prévoit que " a une capacité ".

classe abstraite: Pour mettre en œuvre les mêmes ou différents comportements entre plusieurs objets. Il établit " est une relation.

Oracle site web fournit les principales différences entre interface et abstract de la classe.

envisager d'utiliser les classes abstraites si:

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

envisager d'utiliser des interfaces si:

  1. vous vous attendez à ce que des classes indépendantes implémentent votre interface. Par exemple, de nombreux objets indépendants peuvent implémenter l'interface Serializable .
  2. vous voulez spécifier le comportement d'un type de données particulier, mais ne vous souciez pas de savoir qui met en œuvre son comportement.
  3. Vous voulez profiter de l'héritage multiple de type.

exemple:

classe Abstraite ( EST UN )

Lecteur est une classe abstraite.

BufferedReader est un Reader

FileReader est un Reader

FileReader et BufferedReader sont utilisés à des fins communes : la lecture de données, et ils sont liés par la classe Reader .

Interface ( a une capacité)

Serialisable est une interface.

supposer que vous avez deux classes dans votre application, qui mettent en œuvre Serializable interface

Employee implements Serializable

Game implements Serializable

ici vous ne pouvez pas établir relation par Serializable interface entre Employee et Game , qui sont destinés à des fins différentes. Les deux sont capables de sérialiser l'état et la comparaison se termine là.

regardez ces messages:

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

25
répondu Ravindra babu 2017-09-27 14:01:51

j'ai écrit un article sur quand utiliser une classe abstraite et quand utiliser une interface. Il y a beaucoup plus de différence entre eux que "l'un est-A... et l'on PEUT FAIRE...". Pour moi, ceux sont les conserves de réponses. Je mentionne quelques-unes des raisons quand utiliser l'un ou l'autre. Espérons que cela aide.

http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface /

10
répondu 2009-02-12 19:19:33

1.Si vous créez quelque chose qui fournit des fonctionnalités communes à des classes non liées, 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.

9
répondu kuttychutty 2013-04-04 04:05:43
Les Classes

peuvent hériter d'une seule classe de base, donc si vous voulez utiliser les classes abstraites pour fournir le polymorphisme à un groupe de classes, ils doivent tous hériter de cette classe. Les classes abstraites peuvent aussi fournir des membres qui ont déjà été implémentés. Par conséquent, vous pouvez assurer une certaine quantité de fonctionnalité identique avec une classe abstraite, mais pas avec une interface.

voici quelques recommandations pour vous aider à décider s'il faut utiliser une interface ou une classe abstraite pour fournir polymorphisme pour vos composants.

  • si vous prévoyez créer plusieurs versions de votre composant, créez une classe abstraite. Les classes abstraites offrent un moyen simple et facile de modifier 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 de l'interface est requise, vous devez créer une toute nouvelle interface.
  • si la fonctionnalité que vous créez sera utile pour un large éventail d'objets disparates, utilisez une interface. Les classes abstraites devraient être utilisées principalement pour les objets étroitement apparentés, tandis que les interfaces sont les mieux adaptées pour fournir des fonctionnalités communes à des classes non apparentées.
  • Si vous concevez de petits bits concis de fonctionnalité, utilisez des interfaces. Si vous êtes à la conception grandes unités fonctionnelles, utilisez une classe abstraite.
  • si vous voulez fournir des fonctionnalités communes mises en œuvre 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é de:

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

3
répondu Mazhar 2014-12-13 08:36:08

envisager d'utiliser classes abstraites si l'un de ces énoncés s'applique à votre situation:

  1. vous voulez partager le code entre plusieurs classes étroitement liées.
  2. vous vous attendez à ce que les classes qui étendent votre classe abstraite aient beaucoup de méthodes ou de champs communs ou nécessitent des modificateurs d'accès autres que publics (tels que protégé et privé).
  3. vous voulez déclarer non-statique ou non-final Fields. Cela vous permet de définir les méthodes qui peut accéder et modifier l'état de l'objet à laquelle ils appartiennent.

envisagez d'utiliser interfaces si l'un de ces énoncés s'applique à votre situation:

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

Source

3
répondu Abhijeet Ashok Muneshwar 2017-04-21 07:11:02

je pense que la façon la plus succincte de l'exprimer est la suivante:

Partagé propriétés => 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) { }
}

parce que les animaux ont une propriété partagée - nombre de jambes dans ce cas il est logique de faire une classe abstraite contenant cette propriété partagée. Cela nous permet également d'écrire le code commun qui opère 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 les Vuvuzelas et les voitures sont des choses complètement différentes, mais elles ont une fonctionnalité partagée: faire un son. Ainsi, une interface a du sens ici. De plus, il permettra aux programmeurs de grouper les choses qui font des sons ensemble sous un interface -- IMakeSound dans ce cas. Avec cette conception, vous pourriez é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 donnerait?

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 exigeons que tous les BaseAnimal fassent un son, mais nous ne connaissons pas encore son implémentation. Dans un tel cas, nous pouvons abstraire l'interface mise en œuvre et déléguer sa mise en œuvre à 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.

3
répondu Domn Werner 2017-06-14 15:23:44

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

2
répondu Nick Fortescue 2009-01-26 08:55:12

pour moi, j'utiliserais des interfaces dans de nombreux cas. Mais je préfère les cours abstraits dans certains cas.

Classes dans OO generaly se réfère à la mise en œuvre. J'utilise des classes abstraites quand je veux forcer des 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 la mise en œuvre, mais aussi pour partager certains détails spécifiques parmi de nombreuses classes connexes.

2
répondu La VloZ Merrill 2017-07-13 20:34:21

utilisez une classe abstraite si vous voulez fournir quelques implémentations de base.

1
répondu Sebastian 2009-01-26 08:48:46

en java, vous pouvez hériter d'une classe (abstraite) à la fonctionnalité "fournir" et vous pouvez mettre en œuvre de nombreuses interfaces pour "assurer" la fonctionnalité

1
répondu Peter Miehle 2009-01-26 08:52:18

purement sur la base de l'héritage, vous utiliserez un Abstrait où vous définirez clairement les relations descendantes, abstraites (i.e. animal->cat) et/ou exigerez l'héritage de propriétés virtuelles ou non publiques, en particulier l'état partagé (que les Interfaces ne peuvent pas supporter).

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 de support les tests unitaires, la séparation des préoccupations et l'héritage (variable de langue) multiple d'une manière que les résumés ne peuvent pas.

1
répondu annakata 2009-01-26 08:56:55

un endroit intéressant où les interfaces se portent mieux que les classes abstraites est quand vous avez besoin d'ajouter des fonctionnalités supplémentaires à un groupe d'objets (apparentés ou non). Si vous ne pouvez pas leur donner une classe d'abstrait de base (par exemple, ils sont sealed ou ont déjà un parent), vous pouvez leur donner une interface factice (vide) à la place, et ensuite simplement écrire des méthodes d'extension pour cette interface.

1
répondu Dmitri Nesteruk 2009-01-26 11:00:47

Cela peut être très difficile de décider...

un pointeur que je peux donner: un objet peut implémenter plusieurs interfaces, alors 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 un héritage multiple - mais n'est-ce pas mal vu?)

0
répondu Mesh 2009-01-26 08:53:30

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 aussi y avoir des différences liées à la langue: par exemple, C# n'a pas d'héritage multiple, mais plusieurs interfaces peuvent être implémentées dans une classe.

0
répondu Gerrie Schenck 2009-01-26 08:54:14

la règle de base du pouce est la suivante: pour "noms" utiliser L'abrégé classe et pour "verbes" utiliser l'interface

e. g: car est une classe abstraite et drive , nous pouvons en faire une interface.

-1
répondu GANI 2015-05-09 08:34:10