Y a-t-il une différence entre les interfaces et les classes abstraites qui ont uniquement des méthodes abstraites?

9

Disons que nous avons une classe abstraite et que cette classe n'a que des méthodes abstraites. Cette classe abstraite est-elle différente d'une interface qui n'a que les mêmes méthodes?

Ce que je cherche à savoir, c'est s'il y a des différences à la fois philosophiquement, objectivement et dans l'implémentation du langage de programmation sous-jacent entre une classe abstraite avec uniquement des membres abstraits et une interface équivalente?

yfklon
la source
quelle langue?
kevin cline
pour autant que je sache, on répond deux fois à votre question : ici et ici . Et ces deux réponses sont indépendantes du langage, rien de spécifique pour C # là
gnat
3
@blank Je n'étais pas d'accord avec le statut Duplicate appliqué à votre question, je l'ai donc rouverte. De plus, j'ai modifié votre question pour clarifier davantage ce que je pense que vous demandez.
maple_shaft

Réponses:

22

Techniquement, les différences ne sont pas vraiment importantes mais, conceptuellement, ce sont des choses entièrement différentes et cela conduit aux différences techniques que d'autres ont mentionnées.

Une superclasse abstraite est exactement ce à quoi elle ressemble, c'est un type commun qui est partagé par de nombreux autres types, comme les chats et les chiens sont des animaux.

Une interface est également exactement ce à quoi elle ressemble, c'est une interface à travers laquelle d'autres classes peuvent communiquer avec l'objet. Si vous voulez faire un Cat Walk, ça va, car Cat implémente une interface CanWalk. Pareil pour un lézard, mais ils marchent très différemment. Un serpent, d'autre part, n'implémente pas CanWalk, vous ne pouvez donc pas lui dire de marcher. Pendant ce temps, Lizard et Snake (ou peut-être des sous-classes plus explicites - je ne suis pas un expert) pourraient tous deux se débarrasser de leur peau, et donc implémenter CanShed, tandis qu'un chat ne pourrait pas le faire.

Mais ils sont tous toujours des animaux et ont des propriétés communes, comme s'ils sont vivants ou morts.

C'est pourquoi toutes les méthodes d'une interface doivent être implémentées en tant que public (ou explicitement, en C #). Parce que quel est le point dans une interface qui est cachée de la classe d'interface avec l'objet? C'est aussi pourquoi vous pouvez avoir plusieurs interfaces vers un objet, même lorsqu'un langage ne prend pas en charge l'héritage multiple.

Pour revenir à votre question, lorsque vous la regardez de cette façon, il y a très rarement une raison d'avoir une superclasse entièrement abstraite.

pdr
la source
4
+1, bien que les chats perdent de manière beaucoup plus agaçante que les serpents ou les lézards.
Matthew Flynn
Techniquement: les méthodes abstraites peuvent être protégées. Les méthodes d'interface ne peuvent pas.
Jacques Koorts
19

Dans la plupart des langages POO, une classe d'implémentation ne peut dériver que d'une seule classe abstraite, mais implémenter plusieurs interfaces.

herzmeister
la source
3
plus? lesquels comptez-vous? La plupart des langages POO que je connais n'ont pas d'interfaces ou de classes abstraites. C ++ n'a que des classes abstraites.
kevin cline
10
@kevincline: probablement C #, Java et VB.NET.
tdammers
1
@kevincline, je pense qu'il manque juste un "avoir les deux". IIRC, à Ada, la motivation pour l'interface était celle-là, les concepteurs ne voulaient pas d'une fonctionnalité d'héritage multiple général, mais le cas spécial de l'interface était jugé trop important pour ne pas être fourni.
AProgrammer le
@tdammers: LOL. C'était une blague, non?
kevin cline
3

Dans un langage comme C ++ qui permet l'héritage multiple et n'a pas d'interfaces, les classes abstraites dans lesquelles toutes les méthodes sont abstraites peuvent servir d'interfaces. Je n'ai pas beaucoup travaillé avec C ++, mais je suppose que l'héritage multiple peut causer des problèmes lorsqu'il existe des méthodes portant le même nom dans les classes de base.

Dans des langages comme PHP et C #, les interfaces fournissent un moyen d'obtenir un polymorphisme similaire, bien que je n'aime pas l'appeler "héritage" car il existe une différence conceptuelle entre hériter une classe abstraite et implémenter une interface. Les interfaces éliminent le problème de conflit, car elles-mêmes ne fournissent aucune implémentation.

Une interface sert de contrat au monde extérieur, tandis qu'une classe abstraite peut fournir une implémentation, bien que si elle est utilisée pour «simuler» une interface, elle ne le sera probablement pas.

La principale différence conceptuelle est que lorsqu'une classe hérite d'une autre classe (abstraite ou non), il y a une relation de "est", donc a Carest un Vehicleet Dogest un Animal. Avec une interface, c'est ce que fait l'objet qui compte. Donc , à la fois Caret Dogpeut Move()et le consommateur le sait parce qu'ils mettent en œuvre Movable, mais une voiture est certainement pas Dog, ou un Animal. Et l'implémentation du mouvement sera différente (roues vs jambes) mais le code consommateur ne s'en soucie pas et ne devrait pas s'en soucier. Les interfaces concernent le code consommateur plutôt que l'implémentation.

Le point principal est que si vous avez des interfaces dans la langue de votre choix, utilisez-les pour les choses pour lesquelles elles sont là. Sinon (comme en C ++), vous pouvez les simuler en utilisant des classes abstraites pures.

Ivan Pintar
la source
L'interface est également un type, vous pouvez donc avoir un IAnimal qui est à la fois Doget Cat sont .
Amy Blankenship
Vous pourriez, mais à mon avis, les interfaces concernent le comportement qui est exposé au monde extérieur, et pas tellement ce que sont les objets. L'héritage implique que quelque chose est un type d'autre chose (le chat est un animal). Une interface indique simplement ce que cet objet peut faire. C'est pourquoi j'aime dire que quelque chose "implémente" plutôt que "hérite" d'une interface, ce que diraient la plupart des gens .Net avec qui j'ai travaillé (je suppose que la syntaxe est la même pour l'héritage et l'implémentation).
Ivan Pintar
2

Les classes abstraites peuvent comporter des méthodes protégées abstraites (dans les langues avec lesquelles je travaille), dans les interfaces les méthodes sont généralement toujours publiques. Je ne sais pas si cette différence permet des exploitations utiles.

Edit J'ai d'abord pensé qu'une méthode abstraite privée n'était d'aucune utilité, mais maintenant je me suis rappelé qu'elle peut être utilisée pour s'assurer que cette méthode n'est jamais appelée. De cette façon, vous pouvez empêcher l'appel d'un constructeur de copie d'un objet.

Thomas
la source
1
Les méthodes virtuelles protégées (remplaçables) peuvent être utiles pour les classes qui font partie d'un framework ou quelque chose comme ça. De cette façon, ils s'assurent que le code personnalisé dans une classe qui hérite du résumé fournit cette fonctionnalité. Bien que cela puisse également être réalisé en héritant d'une interface sur la classe de base mais en n'implémentant pas réellement ses méthodes
Ivan Pintar
Oui, je pensais à quelque chose comme ça, mais je n'ai aucune expérience avec ça, donc je ne pouvais pas juger. Merci pour la contribution.
Thomas
Juste une note. Dans certains langages, les méthodes virtuelles privées peuvent être remplacées dans les classes dérivées.
Johan Boulé
2

Oui, ils sont différents. Sinon, les concepteurs de langage n'auraient pas fourni les deux. Je connais deux langages qui séparent les classes et les interfaces: Java et C #, clone mutant de Java. Les concepteurs ont créé des interfaces pour éviter de prendre en charge l'héritage de plusieurs classes. La plupart des autres langages prennent en charge l'héritage de plusieurs classes et, par conséquent, ne séparent pas les classes et les interfaces.

kevin cline
la source
2

Je pense que la principale différence est que: dans une classe abstraite - même si toutes les méthodes sont toutes abstraites, elles peuvent toujours fournir des membres de données (variables d'instance) et du code aux classes qui l'implémentent (sous forme de méthodes privées ou de constructeurs), blocs statiques; faire une partie du travail pour les sous-classes et les aider dans la mise en œuvre.

Un effet secondaire positif: le code est en un seul endroit, donc un endroit pour apporter des corrections. les sous-classes peuvent simplement appeler la méthode de super classe et ensuite faire autre chose ou rien si les actions de super classe sont suffisantes pour leur cas. La super classe veut que chaque sous-classe prenne cette décision, elle a donc marqué toute son implémentation comme abstraite (certaines pourraient aussi être vides)

Pas pertinent pour la question: mais avoir des interfaces signifie qu'une classe peut implémenter deux contrats différents. Voilà donc un avantage d'une interface sur une super classe abstraite

tgkprog
la source
1
Les méthodes abstraites ne sont-elles pas définies sans implémentation et laissent-elles l'implémentation aux classes héritières?
Ivan Pintar
oui, vous avez raison, je suppose que ce ne sont que les variables, les constructeurs et les méthodes statiques et privées si vous les comptez
tgkprog
@Pinetree, dans la pratique la plupart du temps, vous voudrez au moins un peu de "vrai" code dans vos classes abstraites (au moins dans le langage que j'utilise, qui n'a pas de construction spéciale pour les classes abstraites).
Amy Blankenship
@AmyBlankenship oui, la plupart du temps les classes abstraites ont du "vrai" code (c'est pour ça qu'elles sont là). Mais je parlais de méthodes abstraites, dans le contexte d'une classe purement abstraite qui sert d'interface dans un langage comme C ++, qui n'a pas d'interfaces.
Ivan Pintar