J'ai récemment eu deux entretiens téléphoniques au cours desquels on m'a interrogé sur les différences entre une classe Interface et une classe Abstract. J'ai expliqué tous les aspects auxquels je pouvais penser, mais il semblerait qu'ils attendent que je mentionne quelque chose de spécifique, et je ne sais pas ce que c'est.
D'après mon expérience, je pense que ce qui suit est vrai. Si je manque un point majeur s'il vous plaît faites le moi savoir.
Interface:
Chaque méthode déclarée dans une interface devra être implémentée dans la sous-classe . Seuls les événements, les délégués, les propriétés (C #) et les méthodes peuvent exister dans une interface. Une classe peut implémenter plusieurs interfaces.
Classe abstraite:
Seules les méthodes abstraites doivent être implémentées par la sous-classe. Une classe abstraite peut avoir des méthodes normales avec des implémentations. La classe abstraite peut également avoir des variables de classe en plus des événements, des délégués, des propriétés et des méthodes. Une classe ne peut implémenter qu'une classe abstraite uniquement en raison de la non-existence de l'héritage multiple en C #.
Après tout cela, l'intervieweur a posé la question "Et si vous aviez une classe abstraite avec uniquement des méthodes abstraites? En quoi cela serait-il différent d'une interface?" Je ne connaissais pas la réponse, mais je pense que c'est l'héritage mentionné ci-dessus, n'est-ce pas?
Un autre intervieweur m'a demandé quoi si vous aviez une variable publique dans l'interface, en quoi cela serait-il différent de celui de Abstract Class? J'ai insisté sur le fait que vous ne pouvez pas avoir une variable publique dans une interface. Je ne savais pas ce qu'il voulait entendre mais il n'était pas satisfait non plus.
Voir également:
Alors que votre question indique que c'est pour "OO général", il semble vraiment se concentrer sur. Net Utilisation de ces termes.
En .NET (similaire pour Java):
En termes généraux OO, les différences ne sont pas nécessairement bien définies. Par exemple, certains programmeurs C++ peuvent contenir des définitions rigides similaires (les interfaces sont un sous-ensemble strict de classes abstraites qui ne peuvent pas contenir d’implémentation), tandis que certains peuvent affirmer qu’une classe abstraite avec certaines implémentations par défaut est toujours une interface ou qu’une interface non abstraite est utilisée. La classe peut toujours définir une interface.
En effet, il existe un idiome C++ appelé interface non virtuelle (NVI) dans lequel les méthodes publiques sont des méthodes non virtuelles qui «s'adonnent» aux méthodes virtuelles privées:
Que diriez-vous d’une analogie: lorsque j’étais dans l’armée de l’air, j’ai suivi une formation de pilote et je suis devenu pilote de la USAF (US Air Force). À ce stade, je n'étais pas qualifié pour piloter quoi que ce soit et je devais assister à une formation sur type d'aéronef. Une fois que je me suis qualifié, j'étais pilote (classe abstraite) et pilote C-141 (classe concrète). Lors de l'une de mes tâches, on m'a confié une tâche supplémentaire: agent de sécurité. À l’heure actuelle, j’étais encore pilote et pilote du C-141, mais j’ai également assumé des fonctions de responsable de la sécurité (j’ai mis en œuvre ISafetyOfficer, pour ainsi dire). Un pilote n'était pas obligé d'être un agent de sécurité, d'autres personnes auraient pu le faire aussi.
Tous les pilotes de l'US Air Force doivent respecter certaines réglementations applicables à l'ensemble de l'armée de l'air et tous les pilotes de C-141 (ou F-16 ou T-38) sont des pilotes de l'US Air Force. Tout le monde peut être un agent de sécurité. Donc, pour résumer:
remarque ajoutée: il s’agissait d’une analogie permettant d’expliquer le concept et non d’une recommandation de codage. Voir les différents commentaires ci-dessous, la discussion est intéressante.
Je pense que la réponse qu'ils recherchent est la différence fondamentale ou philosophique OPPS.
L'héritage de classe abstraite est utilisé lorsque la classe dérivée partage les propriétés principales et le comportement de la classe abstraite. Le genre de comportement qui définit réellement la classe.
Par ailleurs, l'héritage d'interface est utilisé lorsque les classes partagent un comportement périphérique, celles qui ne définissent pas nécessairement la classe dérivée.
Pour par exemple. Une voiture et un camion partagent de nombreuses propriétés fondamentales et le comportement d'une classe abstraite Automobile, mais ils partagent également certains comportements périphériques, tels que Générer un échappement, que même les classes non automobiles telles que Drillers ou PowerGenerators ne définissent pas nécessairement comme une voiture ou un camion. , de sorte que les voitures, camions, foreuses et PowerGenerator peuvent tous partager la même interface IExhaust.
Short: les classes abstraites sont utilisées pour Modélisation une hiérarchie de classes de classes similaires (par exemple, Animal peut être une classe abstraite et Human, Lion, Tiger peuvent être des classes dérivées concrètes)
ET
Interface est utilisée pour Communication entre 2 classes similaires/non similaires ne se souciant pas du type de la classe implémentant Interface (eg, Height peut être une propriété d'interface et il peut être implémenté par Human, Building, Tree. Peu importe si vous pouvez manger, vous pouvez nager, vous pouvez mourir ou n'importe quoi .. il importe seulement une chose dont vous avez besoin d'avoir Height (implémentation dans votre classe)).
Il y a quelques autres différences -
Les interfaces ne peuvent avoir aucune implémentation concrète. Les classes de base abstraites peuvent. Cela vous permet d’y apporter des implémentations concrètes. Cela peut permettre à une classe de base abstraite de fournir un contrat plus rigoureux, une interface décrivant uniquement la manière dont une classe est utilisée. (La classe de base abstraite peut avoir des membres non virtuels définissant le comportement, ce qui donne plus de contrôle à l'auteur de la classe de base.)
Plusieurs interfaces peuvent être implémentées sur une classe. Une classe ne peut dériver que d'une seule classe de base abstraite. Cela permet une hiérarchie polymorphe utilisant des interfaces, mais pas des classes de base abstraites. Cela permet également un pseudo-multi-héritage en utilisant des interfaces.
Les classes de base abstraites peuvent être modifiées en v2 + sans casser l'API. Les modifications apportées aux interfaces annulent les modifications.
[C #/.NET Specific] Contrairement aux classes de base abstraites, les interfaces peuvent être appliquées à des types de valeur (struct). Les structures ne peuvent pas hériter des classes de base abstraites. Cela permet d'appliquer des directives comportementales/d'utilisation comportementales sur les types de valeur.
Héritage
Considérons une voiture et un bus. Ce sont deux véhicules différents. Mais ils partagent néanmoins certaines propriétés communes, comme la direction, les freins, les engrenages, le moteur, etc.
Donc, avec le concept d'héritage, cela peut être représenté comme suit ...
public class Vehicle {
private Driver driver;
private Seat[] seatArray; //In Java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
//You can define as many properties as you want here ...
}
Maintenant un vélo ...
public class Bicycle extends Vehicle {
//You define properties which are unique to bicycles here ...
private Pedal pedal;
}
Et une voiture ...
public class Car extends Vehicle {
private Engine engine;
private Door[] doors;
}
C'est tout à propos de héritage. Nous les utilisons pour classer les objets dans des formes de base plus simples et leurs enfants comme nous l'avons vu ci-dessus.
Classes abstraites
Les classes abstraites sont des objets incomplets. Pour mieux comprendre, considérons une fois encore l'analogie véhicule.
Un véhicule peut être conduit. Droite? Mais différents véhicules sont conduits de différentes manières ... Par exemple, vous ne pouvez pas conduire une voiture comme vous conduisez un vélo.
Alors, comment représenter la fonction de conduite d'un véhicule? Il est plus difficile de vérifier le type de véhicule et de le conduire avec sa propre fonction. vous devrez changer la classe de conducteur encore et encore lors de l'ajout d'un nouveau type de véhicule.
Voici le rôle des classes et méthodes abstraites. Vous pouvez définir la méthode de lecteur comme abstraite pour indiquer que tous les enfants hérités doivent implémenter cette fonction.
Donc si vous modifiez la classe de véhicule ...
//......Code of Vehicle Class
abstract public void drive();
//.....Code continues
Le vélo et la voiture doivent également spécifier comment le conduire. Sinon, le code ne sera pas compilé et une erreur est générée.
En bref, une classe abstraite est une classe partiellement incomplète avec des fonctions incomplètes, que les enfants héritiers doivent spécifier.
Interfaces Les interfaces sont totalement incomplètes. Ils n'ont aucune propriété. Ils indiquent simplement que les enfants héritiers sont capables de faire quelque chose ...
Supposons que vous ayez différents types de téléphones mobiles. Chacun d’entre eux a différentes façons de remplir différentes fonctions; Ex: appeler une personne. Le fabricant du téléphone précise comment procéder. Ici, les téléphones mobiles peuvent composer un numéro - c’est-à-dire qu’il peut être composé. Représentons cela comme une interface.
public interface Dialable {
public void dial(Number n);
}
Ici, le fabricant du Dialable définit comment composer un numéro. Vous avez juste besoin de lui donner un numéro à composer.
// Makers define how exactly dialable work inside.
Dialable PHONE1 = new Dialable() {
public void dial(Number n) {
//Do the phone1's own way to dial a number
}
}
Dialable PHONE2 = new Dialable() {
public void dial(Number n) {
//Do the phone2's own way to dial a number
}
}
//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
Dialable myDialable = SomeLibrary.PHONE1;
SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....
En utilisant des interfaces au lieu de classes abstraites, l’écrivain de la fonction qui utilise un Dialable n’a pas à s’inquiéter de ses propriétés. Ex: dispose-t-il d'un écran tactile ou d'un clavier téléphonique? S'agit-il d'un téléphone fixe ou d'un téléphone portable? Vous avez juste besoin de savoir si vous pouvez le composer. hérite-t-il (ou implémente-t-il) l'interface Dialable?
Et plus important encore}, si un jour vous commutez le Dialable avec un autre
......
public static void main(String[] args) {
Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....
Vous pouvez être sûr que le code fonctionne toujours parfaitement car la fonction qui utilise le dialable ne dépend pas (et ne peut pas) des détails autres que ceux spécifiés dans l'interface dialable. Ils implémentent tous les deux une interface Dialable et c'est la seule chose qui intéresse la fonction.
Les développeurs utilisent couramment les interfaces pour assurer l’interopérabilité (utilisation interchangeable) entre les objets, dans la mesure où ils partagent une fonction commune (tout comme vous pouvez passer à un téléphone fixe ou mobile, dans la mesure où vous avez juste besoin de composer un numéro). En bref, les interfaces sont une version beaucoup plus simple des classes abstraites, sans aucune propriété.
Notez également que vous pouvez implémenter (hériter) autant d’interfaces que vous le souhaitez, mais que vous ne pouvez étendre (hériter) qu’une seule classe parente.
Plus d'infosClasses abstraites vs interfaces
Si vous considérez que Java
est la langue OOP pour répondre à cette question, la version Java 8 rend obsolète une partie du contenu des réponses ci-dessus. Maintenant, l'interface Java peut avoir des méthodes par défaut avec une implémentation concrète.
Oracle website fournit les principales différences entre les classes interface
et abstract
.
Envisagez d'utiliser des classes abstraites si:
Pensez à utiliser les interfaces si:
Serializable
.En termes simples, je voudrais utiliser
interface: _ Pour implémenter un contrat avec plusieurs objets non liés
classe abstraite: _ Pour appliquer le même comportement ou un comportement différent entre plusieurs objets liés
Regardez exemple de code pour comprendre les choses clairement: Comment aurais-je dû expliquer la différence entre une classe Interface et une classe abstraite?
Les enquêteurs aboient un arbre étrange. Pour les langages tels que C # et Java, il y a une différence, mais dans d'autres langages comme C++, il n'y en a pas. La théorie OO ne différencie pas les deux, mais simplement la syntaxe du langage.
Une classe abstraite est une classe avec à la fois une implémentation et une interface (méthodes virtuelles pures) qui sera héritée. Les interfaces n'ont généralement aucune implémentation, mais uniquement des fonctions virtuelles pures.
En C # ou Java, une classe abstraite sans aucune implémentation ne diffère d'une interface uniquement par la syntaxe utilisée pour en hériter et par le fait que vous ne pouvez en hériter que par une.
En implémentant des interfaces, vous obtenez une composition (relations "has-a") au lieu d'un héritage (relations "is-a"). C’est un principe important à garder à l’esprit lorsque, par exemple, les modèles de conception nécessitent l’utilisation d’interfaces pour obtenir une composition de comportements plutôt qu’un héritage.
je vais expliquer les détails de profondeur des classes interface et abstract.si vous connaissez la présentation générale des classes interface et abstraite, vous devez d'abord vous poser la question de savoir quand vous devriez utiliser Interface et quand utiliser la classe abstraite . Classe d'interface et abstraite.
Quand devrions-nous utiliser l'interface?
si vous ne connaissez pas l'implémentation, nous avons juste une spécification des exigences, puis nous allons avec Interface
Quand faut-il utiliser la classe abstraite?
si vous connaissez l'implémentation mais pas complètement (partiellement l'implémentation), alors nous allons avec la classe abstraite.
Interface
chaque méthode par défaut public abstract signifie interface est 100% pur abstrait.
Abstrait
peut avoir une méthode concrète et une méthode abstraite, quelle est la méthode concrète, qui sont implémentées dans la classe abstraite, Une classe abstraite est une classe déclarée abstraite. Elle peut inclure ou non des méthodes abstraites.
Interface
Nous ne pouvons pas déclarer une interface privée, protégée
Q. Pourquoi ne déclarons-nous pas Interface privée et protégée?
Parce que, par défaut, la méthode d'interface est publique abstraite, et ainsi de suite, nous ne déclarons pas l'interface privée et protégée.
Méthode d'interface
De plus, nous ne pouvons pas déclarer une interface privée, protégée, finale, statique, synchronisée, native, etc.
je vais donner la raison: pourquoi nous ne déclarons pas la méthode synchronisée parce que nous ne pouvons pas créer d'objet d'interface et que synchronize ne fonctionne pas sur l'objet et sur la raison que nous ne déclarons pas la méthode synchronisée Le concept de transitoire ne s'applique pas non plus car le transitoire fonctionne avec synchronisé.
Abstrait
nous sommes heureux d’utiliser avec public, private final static .... signifie qu'aucune restriction ne s'applique dans l’abrégé.
Interface
Les variables sont déclarées dans Interface comme une finale publique statique par défaut, de sorte que nous ne sommes pas non plus déclarées comme variable privée, protégée.
Le modificateur Volatile n'est pas non plus applicable dans l'interface, car la variable d'interface est par défaut une variable publique statique finale et une variable finale publique. Vous ne pouvez pas modifier la valeur une fois qu'elle a été affectée à une variable et qu'une fois que vous avez déclaré une variable à une interface, vous devez l'affecter.
Et la variable volatile est de garder les changements donc c'est opp. au final c'est la raison pour laquelle nous n'utilisons pas de variable volatile dans l'interface.
Abstrait
Variable abstraite inutile de déclarer publique statique final.
j'espère que cet article est utile.
Sur le plan conceptuel, conserver l'implémentation, les règles et les avantages spécifiques au langage et atteindre tout objectif de programmation en utilisant n'importe qui ou les deux peut avoir ou ne pas avoir de code/données/propriété, bla bla, héritage unique ou multiple, le tout mis de côté
1- Abstract (ou pure abstract) Class est destiné à implémenter une hiérarchie. Si vos objets métier ont une structure similaire, représentant un type de relation parent-enfant (hiérarchie) uniquement, les classes héritage/abstrait seront utilisées. Si votre modèle d'entreprise ne comporte pas de hiérarchie, l'héritage ne doit pas être utilisé (ici, je ne parle pas de logique de programmation, par exemple, certains modèles de conception nécessitent un héritage). Conceptuellement, la classe abstraite est une méthode permettant d'implémenter la hiérarchie d'un modèle d'entreprise dans la POO, elle n'a rien à voir avec les interfaces. En fait, comparer une classe abstraite à une interface n'a pas de sens parce que les deux sont conceptuellement des choses totalement différentes. Les concepts, car il semble que les deux offrent à peu près les mêmes fonctionnalités en ce qui concerne l'implémentation et nous, programmeurs, insistons généralement sur le codage [Gardez ceci à l'esprit aussi, que l'abstraction est différente de la classe abstraite].
2- une interface est un contrat, une fonctionnalité métier complète représentée par un ou plusieurs ensembles de fonctions. C'est pourquoi il est implémenté et non hérité. Un objet métier (faisant partie d'une hiérarchie ou non) peut avoir un nombre quelconque de fonctionnalités métier complètes. Cela n'a rien à voir avec les classes abstraites signifie héritage en général. Par exemple, un humain peut RUN, un éléphant peut RUN, un oiseau peut RUN, etc., tous ces objets de hiérarchies différentes implémentent l'interface RUN ou les interfaces EAT ou SPEAK. N'entrez pas dans l'implémentation car vous pourriez l'implémenter en ayant des classes abstraites pour chaque type implémentant ces interfaces. Un objet de toute hiérarchie peut avoir une fonctionnalité (interface) qui n’a rien à voir avec sa hiérarchie.
Je crois que les interfaces n’ont pas été inventées pour obtenir de multiples héritages ou pour exposer un comportement public. De même, les classes abstraites pures ne sont pas destinées à écraser les interfaces, mais Interface est une fonctionnalité qu’un objet peut utiliser (via les fonctions de cette interface) et Abstract Class représente une parent d'une hiérarchie pour produire des enfants ayant une structure de base (propriété + fonctionnalité) du parent
Lorsqu'on vous demande quelle est la différence, il s'agit en réalité d'une différence conceptuelle et non d'une différence dans la mise en œuvre spécifique à une langue, sauf demande explicite.
Je crois que les deux intervieweurs s'attendaient à une différence directe entre les deux. Lorsque vous avez échoué, ils ont essayé de vous amener à cette différence en mettant en œuvre ONE comme AUTRE.
Et si vous aviez une classe Abstract avec uniquement des méthodes abstraites?
Pour .Net,
Votre réponse au deuxième intervieweur est également la réponse au premier ... Les classes abstraites peuvent avoir une implémentation, ET un état, les interfaces ne peuvent pas ...
EDIT: Sur une autre note, je n’utiliserais même pas l’expression «sous-classe» (ou l’expression «héritage») pour décrire les classes définies pour implémenter une interface. Pour moi, une interface est la définition d'un contrat auquel une classe doit se conformer si elle a été définie pour "implémenter" cette interface. Il n'hérite de rien ... Vous devez tout ajouter vous-même, explicitement.
Je pense qu'ils n'ont pas aimé votre réponse parce que vous avez indiqué les différences techniques au lieu de différences de conception. La question est comme une question de troll pour moi. En fait, les interfaces et les classes abstraites ont une nature complètement différente, vous ne pouvez donc pas vraiment les comparer. Je vais vous donner ma vision de ce qui est le rôle d'une interface et quel est le rôle d'une classe abstraite.
interface: est utilisé pour garantir un contrat et créer un faible couplage entre les classes afin de disposer d'une application plus maintenable, évolutive et testable.
classe abstraite: sert uniquement à factoriser du code entre des classes de la même responsabilité. Notez que c'est la raison principale pour laquelle l'héritage multiple est une mauvaise chose en POO, car une classe ne devrait pas gérer plusieurs responsabilités (utilisez plutôt composition à la place).
Les interfaces ont donc un réel rôle d’architecte alors que les classes abstraites ne sont presque qu’un détail d’implémentation (si vous l’utilisez correctement, bien sûr).
Interface: doit être utilisé si vous souhaitez impliquer une règle sur les composants liés ou non Liés les uns aux autres.
Avantages:
Les inconvénients:
Abstract Class: doit être utilisé lorsque vous souhaitez avoir un comportement ou une implémentation de base ou par défaut pour des composants liés les uns aux autres
Avantages:
Les inconvénients:
After all that, the interviewer came up with the question "What if you had an
Abstract class with only abstract methods? How would that be different
from an interface?"
Docs indique clairement que si une classe abstraite ne contient que des déclarations de méthodes abstraites, elle doit plutôt être déclarée comme interface.
An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?
Les variables dans les interfaces sont par défaut publiques statiques et finales. La question pourrait être formulée comme si toutes les variables de la classe abstraite étaient publiques? Eh bien, elles peuvent toujours être non statiques et non finales, contrairement aux variables des interfaces.
Enfin, j’aimerais ajouter un autre point à ceux mentionnés ci-dessus - les classes abstraites sont toujours des classes et relèvent d’un seul arbre d’héritage, alors que les interfaces peuvent être présentes dans un héritage multiple.
C'est mon opinion.
Copié à partir de CLR via C # par Jeffrey Richter ...
J'entends souvent la question «Devrais-je concevoir un type de base ou une interface?». La réponse n’est pas toujours claire.
Voici quelques lignes directrices qui pourraient vous aider:
■■ Relation IS-A vs CAN-DO Un type ne peut hériter que d'une implémentation. Si le type dérivé Ne peut pas revendiquer une relation IS-A avec le type de base, n’utilisez pas de type de base; utiliser une interface . Les interfaces impliquent une relation CAN-DO. Si la fonctionnalité CAN-DO semble appartenir à plusieurs types d’objets, utilisez une interface. Par exemple, un type peut convertir des instances de lui-mêmeun autre type (IConvertible), un type peut sérialiser une instance de lui-même (ISerializable), , Etc. Notez que les types de valeur doivent être dérivés de System.ValueType et qu’ils ne peuvent donc pas. Être dérivés d’une classe de base arbitraire. Dans ce cas, vous devez utiliser une relation CAN-DO Et définir une interface.
■■ Facilité d’utilisation En tant que développeur, il est généralement plus facile de définir un nouveau type dérivé d’un type de base Que d’implémenter toutes les méthodes d’une interface. Le type de base peut fournir un grand nombre de fonctionnalités. Le type dérivé n'a donc probablement besoin que de modifications minimes de son comportement. Si vous fournissez une interface, le nouveau type doit implémenter tous les membres.
■■ Mise en œuvre cohérente Même si un contrat d’interface est bien documenté, il est très peu probable que tout le monde le mette correctement en œuvre. En fait, COM Souffre de ce problème, c’est pourquoi certains objets COM ne fonctionnent correctement que avec Microsoft Word ou avec Windows Internet Explorer. En fournissant un type de base avec une implémentation correcte Default, vous commencez par utiliser un type qui fonctionne et qui est bien testé; vous pouvez alors modifier les pièces à modifier.
■■ Gestion des versions Si vous ajoutez une méthode au type de base, le type dérivé hérite de la nouvelle méthode. Vous commencez par utiliser un type qui fonctionne et le code source de l'utilisateur n'a même pas besoin d'être recompilé . L'ajout d'un nouveau membre à une interface oblige l'héritier de l'interface à modifier Son code source et à le recompiler.
Une interface définit un contrat pour un service ou un ensemble de services. Elles fournissent un polymorphisme de manière horizontale en ce sens que deux classes totalement indépendantes peuvent implémenter la même interface mais peuvent être utilisées indifféremment en tant que paramètre du type d'interface qu'elles implémentent, les deux classes ayant promis de satisfaire l'ensemble des services définis par l'interface. Les interfaces ne fournissent aucun détail sur la mise en œuvre.
Une classe abstraite définit une structure de base pour ses sous-classes et éventuellement une implémentation partielle. Les classes abstraites fournissent un polymorphisme de manière verticale, mais directionnelle, en ce sens que toute classe qui hérite de la classe abstraite peut être traitée comme une instance de cette classe abstraite, mais pas l'inverse. Les classes abstraites peuvent et contiennent souvent des détails d'implémentation, mais ne peuvent pas être instanciées seules. Seules leurs sous-classes peuvent être "modifiées".
C # permet également l'héritage d'interface, remarquez.
Comme vous avez pu acquérir les connaissances théoriques des experts, je ne passe pas beaucoup de mots à répéter celles-ci, mais laissez-moi vous expliquer avec un exemple simple où nous pouvons utiliser/ne pouvons pas utiliser Interface
et Abstract class
.
Considérez que vous concevez une application pour répertorier toutes les fonctionnalités de Cars. Vous avez besoin d’un héritage commun en plusieurs points, car certaines propriétés telles que DigitalFuelMeter, la climatisation, le réglage du siège, etc. sont communes à toutes les voitures. De même, l'héritage n'est nécessaire que pour certaines classes, car certaines propriétés, telles que le système de freinage (ABS, EBD), ne s'appliquent que pour certaines voitures.
La classe ci-dessous sert de classe de base pour toutes les voitures:
public class Cars
{
public string DigitalFuelMeter()
{
return "I have DigitalFuelMeter";
}
public string AirCondition()
{
return "I have AC";
}
public string SeatAdjust()
{
return "I can Adjust seat";
}
}
Considérez que nous avons une classe distincte pour chaque voiture.
public class Alto : Cars
{
// Have all the features of Car class
}
public class Verna : Cars
{
// Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars
}
public class Cruze : Cars
{
// Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars
}
Considérez que nous avons besoin d’une méthode pour hériter de la technologie de freinage pour les voitures Verna et Cruze (non applicable pour Alto). Bien que les deux utilisent la technologie de freinage, la "technologie" est différente. Nous créons donc une classe abstraite dans laquelle la méthode sera déclarée comme abstraite et devrait être implémentée dans ses classes enfants.
public abstract class Brake
{
public abstract string GetBrakeTechnology();
}
Nous essayons maintenant d'hériter de cette classe abstraite et le type de système de freinage est implémenté dans Verna et Cruze:
public class Verna : Cars,Brake
{
public override string GetBrakeTechnology()
{
return "I use ABS system for braking";
}
}
public class Cruze : Cars,Brake
{
public override string GetBrakeTechnology()
{
return "I use EBD system for braking";
}
}
Voir le problème dans les deux classes ci-dessus? Ils héritent de plusieurs classes que C # .Net n'autorise pas même si la méthode est implémentée dans les enfants. Voici le besoin d'interface.
interface IBrakeTechnology
{
string GetBrakeTechnology();
}
Et la mise en œuvre est donnée ci-dessous:
public class Verna : Cars, IBrakeTechnology
{
public string GetBrakeTechnology()
{
return "I use ABS system for braking";
}
}
public class Cruze : Cars, IBrakeTechnology
{
public string GetBrakeTechnology()
{
return "I use EBD system for braking";
}
}
Désormais, Verna et Cruze peuvent réaliser des héritages multiples avec leur propre type de technologies de freinage avec l’aide d’Interface.
La plupart des réponses se concentrent sur la technique entre la classe abstraite et l'interface, mais techniquement, une interface est fondamentalement une sorte de classe abstraite (sans données ni implémentation), je pense que la différence conceptuelle est loin plus intéressant, et cela pourrait être ce que les enquêteurs sont après.
Un Interface est un accord . Il précise: "voici comment nous allons nous parler". Il ne peut y avoir d’implémentation car ce n’est pas supposé en avoir. C'est un contrat. C'est comme les fichiers d'en-tête .h
en C.
An Classe abstraite est une implémentation incomplète . Une classe peut ou non implémenter une interface, et une classe abstraite n'a pas à l'implémenter complètement. Une classe abstraite sans aucune implémentation est un peu inutile, mais totalement légale.
En gros, toute classe, qu'elle soit abstraite ou non, concerne ce qu'elle est, alors qu'une interface concerne comment vous l'utilisez. Par exemple: Animal
pourrait être une classe abstraite implémentant certaines fonctions métaboliques de base et spécifiant des méthodes abstraites de respiration et de locomotion sans donner d’implémentation, car elle ne sait pas si elle doit respirer par les branchies ou les poumons, et si elle vole, nage, marche ou rampe. Mount
, d'autre part, pourrait être une interface, qui spécifie que vous pouvez monter l'animal sans savoir de quel type d'animal il s'agit (ou si c'est un animal du tout!).
Le fait que dans les coulisses, une interface soit fondamentalement une classe abstraite avec uniquement des méthodes abstraites n'a pas d'importance. Conceptuellement, ils remplissent des rôles totalement différents.
Les interfaces sont un moyen léger d'imposer un comportement particulier. C'est une façon de penser.
Types d'interface vs classes de base abstraites
Adapté du Pro C # 5.0 et du .NET 4.5 Framework book.
Le type d'interface peut sembler très similaire à une classe de base abstraite. Rappelez-vous que, lorsqu'une classe est marquée comme abstraite, elle peut définir un nombre quelconque de membres abstraits pour fournir une interface polymorphe .__ à tous les types dérivés. Cependant, même lorsqu'une classe définit un ensemble de membres Abstraits, elle est également libre de définir un nombre quelconque de constructeurs, de données de champ, de membres non abstraits (avec Implémentation, etc.). Les interfaces, quant à elles, ne contiennent que des définitions de membres abstraits . L’interface polymorphe établie par une classe parent abstraite souffre d’une limitation majeure: les seuls types dérivés prennent en charge les membres définis par le parent abstrait. Toutefois, dans les systèmes logiciels plus volumineux, il est très courant de développer plusieurs hiérarchies de classes qui n'ont pas de parent commun Au-delà de System.Object. Étant donné que les membres abstraits d'une classe de base abstraite s'appliquent uniquement aux types dérivés , Nous n'avons aucun moyen de configurer des types dans différentes hiérarchies pour prendre en charge la même interface polymorphe A titre d'exemple, supposons que vous ayez défini la classe abstraite suivante:
public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
public abstract object Clone();
}
Étant donné cette définition, seuls les membres qui étendent CloneableType peuvent prendre en charge la méthode Clone () Si vous créez un nouvel ensemble de classes qui n’étend pas cette classe de base, vous ne pouvez pas obtenir cette interface polymorphe Vous pouvez également vous rappeler que C # ne prend pas en charge l'héritage multiple pour les classes . Par conséquent, si vous souhaitez créer un MiniVan qui est une voiture et qui est un type CloneableType, vous ne pouvez pas le faire:
// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}
Comme vous pouvez le deviner, les types d'interface viennent à la rescousse. Une fois une interface définie, il peutbe être implémenté par n’importe quelle classe ou structure, dans n’importe quelle hiérarchie, dans n’importe quel espace de noms ou n’importe quel Assembly (Écrit dans n’importe quel langage de programmation .NET). Comme vous pouvez le constater, les interfaces sont hautement polymorphes . Prenez l’interface standard .NET appelée ICloneable, définie dans l’espace de noms System. Cette interface Définit une seule méthode nommée Clone ():
public interface ICloneable
{
object Clone();
}
Réponse à la deuxième question: La variable public
définie dans interface
est static final
par défaut alors que la variable public
dans la classe abstract
est une variable d'instance.
1) Une interface peut être vue comme une pure classe abstraite, c'est la même chose, mais malgré cela, ce n'est pas la même chose pour implémenter une interface et hériter d'une classe abstraite. Lorsque vous héritez de cette classe abstraite pure, vous définissez une hiérarchie -> héritage, si vous implémentez l'interface, vous pouvez en implémenter autant que vous le souhaitez, mais vous ne pouvez hériter que d'une seule classe.
2) Vous pouvez définir une propriété dans une interface. La classe qui implémente cette interface doit donc avoir cette propriété.
Par exemple:
public interface IVariable
{
string name {get; set;}
}
La classe qui implémente cette interface doit avoir une propriété comme celle-là.
Bien que cette question soit assez ancienne, je voudrais ajouter un autre point en faveur des interfaces:
Les interfaces peuvent être injectées à l'aide de n'importe quel outil d'injection de dépendance, où l'injection de classe abstraite est prise en charge par très peu de personnes.
De une autre de mes réponses , traitant principalement du moment où utiliser l’un par rapport à l’autre:
D'après mon expérience, les interfaces sont les meilleures. utilisé lorsque vous avez plusieurs classes qui doivent répondre à la même chose méthode ou méthodes afin qu'ils puissent être utilisé de façon interchangeable par un autre code qui sera écrit contre ceux-ci interface commune des classes. Le meilleur l’utilisation d’une interface est lorsque le le protocole est important mais le la logique sous-jacente peut être différente pour chaque classe. Si vous seriez autrement en dupliquant la logique, considérons abstrait classes ou héritage de classe standard au lieu.
Du point de vue du codage
Une interface peut remplacer une classe abstraite si celle-ci ne comporte que des méthodes abstraites. Sinon, changer de classe abstraite en interface signifie que vous perdrez la possibilité de réutilisation de code fournie par Héritage.
Du point de vue de la conception
Conservez-le en tant que classe abstraite s'il s'agit d'une relation "Est-ce que" et avez besoin d'un sous-ensemble ou de toutes les fonctionnalités Conservez-le comme interface si c'est une relation "devrait faire".
Décidez ce dont vous avez besoin: seulement l'application de la politique, ou la réutilisation du code ET la politique.
Bien sûr, il est important de comprendre le comportement de l'interface et de la classe abstraite dans OOP (et comment les langues les traitent), mais je pense qu'il est également important de comprendre la signification exacte de chaque terme. Pouvez-vous imaginer que la commande if
ne fonctionne pas exactement comme le sens du terme? En outre, certaines langues réduisent encore plus les différences entre une interface et un résumé ... si par hasard les deux termes fonctionnent de manière presque identique, vous pouvez au moins vous définir vous-même où (et pourquoi) les utiliser. utilisé pour.
Si vous lisez certains dictionnaires et autres polices, vous pouvez trouver différentes significations pour le même terme, mais avec des définitions communes. Je pense que ces deux significations que j'ai trouvées dans ce site sont vraiment très bonnes et appropriées.
Interface:
Une chose ou une circonstance qui permet à des éléments séparés et parfois incompatibles de se coordonner efficacement.
Abstrait:
Quelque chose qui concentre en soi les qualités essentielles de tout ce qui est plus étendu ou plus général, ou de plusieurs choses; essence.
Exemple:
Vous avez acheté une voiture et elle a besoin de carburant.
Votre modèle de voiture est XYZ
, qui est du genre ABC
; il s’agit donc d’une voiture concrète, d’un exemple spécifique de voiture. Une voiture n'est pas un objet réel. En fait, c'est un ensemble abstrait de normes (qualités) permettant de créer un objet spécifique. En bref, la voiture est un classe abstraite, il est "quelque chose qui concentre en soi les qualités essentielles de tout ce qui est plus étendu ou plus général".
Le seul carburant correspondant aux spécifications du manuel de la voiture doit être utilisé pour remplir le réservoir de la voiture. En réalité, rien ne vous empêche de faire le plein, mais le moteur ne fonctionnera correctement qu'avec le carburant spécifié. Il est donc préférable de respecter ses exigences. Les conditions stipulent qu'elle accepte, comme les autres voitures du même genre ABC
, un ensemble de carburants standard.
Dans une vue orientée objet, le carburant pour le genre ABC
ne devrait pas être déclaré en tant que classe car il n'y a pas de carburant concret pour un genre spécifique de voiture. Bien que votre voiture puisse accepter une classe abstraite Fuel ou VehicularFuel, vous devez vous rappeler que seule une partie du carburant existant correspond aux spécifications, celles qui mettent en œuvre les exigences de votre manuel de voiture. En bref, ils devraient mettre en œuvre la interface ABCGenreFuel
, qui "... permet de coordonner efficacement des éléments séparés et parfois incompatibles".
De plus, je pense que vous devriez garder à l'esprit le sens du terme classe, qui est (à partir du même site mentionné précédemment):
Classe:
Un certain nombre de personnes ou de choses considérées comme formant un groupe en raison d'attributs, de caractéristiques, de qualités ou de traits communs; gentil;
De cette façon, une classe (ou classe abstraite) ne doit pas représenter uniquement des attributs communs (comme une interface), mais un type de groupe avec des attributs communs. Une interface n'a pas besoin de représenter un type. Il doit représenter des attributs communs. De cette façon, je pense que les classes et les classes abstraites peuvent être utilisées pour représenter des choses qui ne devraient pas souvent changer d’aspects, comme un être humain un mammifère, car elles représentent certaines sortes. Les genres ne devraient pas se changer aussi souvent.
Interface:-
== contract.Whichever classe implémente il doit suivre toutes les spécifications de l'interface.
Un exemple en temps réel serait n'importe quel produit marqué par ISO
.ISO
donne un ensemble de rules/specification
sur la manière dont le produit doit être construit et ce que minimum set of features
il Must
possède.
Ce n'est rien d'autre que subset of properties
product Must have.ISO signera le produit only if it satisfies the its standards
.
Maintenant, regardez ce code
public interface IClock{ //defines a minimum set of specification which a clock should have
public abstract Date getTime();
public abstract int getDate();
}
public class Fasttrack: Clock {
// Must have getTime() and getTime() as it implements IClock
// It also can have other set of feature like
public void startBackgroundLight() {
// watch with internal light in it.
}
.... //Fastrack can support other feature as well
....
....
}
Ici, Fastrack
est appelé en tant que surveillant parce que it has all that features that a watch must suppost
(ensemble minimal de fonctionnalités _).
Pourquoi et quand Résumé:
De MSDN:
Le but d'un abstract class
est de fournir un common definition of a base class
que plusieurs classes dérivées peuvent partager.
Par exemple, une bibliothèque de classes peut définir une classe abstraite utilisée comme paramètre pour bon nombre de ses fonctions et obliger les programmeurs utilisant cette bibliothèque à fournir leur propre implémentation de la classe en créant une classe dérivée. Abstract simply means if you cannot define it completely declare it as an abstract
. La classe d'implémentation achèvera cette implémentation.
Par exemple: supposons que je déclare une classe Recipe
comme résumé mais que je ne sache pas quelle recette doit être Made.Alors, je généraliserai cette classe pour définir le common definition of any recipe
. Le l'implantation de la recette dépendra de la mise en oeuvre d'un plat.
La classe abstraite peut consister en des méthodes abstraites et non en une méthode abstraite. Vous remarquerez donc la différence dans Interface. Par conséquent, toutes les méthodes de votre classe d'implémentation ne doivent pas nécessairement posséder. Vous devez uniquement remplacer les méthodes abstraites.
En mots simples Si vous voulez tight coupling use Interface o/w use in case of lose coupling Abstract Class
Couple d'autres différences:
Les classes abstraites peuvent avoir des méthodes statiques, des propriétés, des champs, etc.
En gros, vous pouvez utiliser la classe abstraite seule même si elle n’est jamais implémentée (par le biais de ses membres statiques) et vous ne pouvez pas utiliser l’interface seule.
La classe abstraite traite efficacement la fonctionnalité de la classe, alors que l'interface est destinée à l'intention/contrat/communication et est supposée être partagée avec d'autres classes/modules.
L'utilisation de classes abstraites à la fois en tant que contrat et en tant qu'implémenteur de contrat (partiel) constitue une violation de SRP. L'utilisation de classes abstraites en tant que contrat (dépendance) limite la création de plusieurs classes abstraites pour une meilleure réutilisation.
Dans l'exemple ci-dessous, l'utilisation de la classe abstraite en tant que contrat avec OrderManager créerait des problèmes, car nous disposons de deux manières différentes de traiter les commandes - en fonction du type et de la catégorie de client (le client peut être direct ou indirect, or ou argent). Par conséquent, l'interface est utilisée pour les contrats et la classe abstraite pour différentes applications du flux de travail
public interface IOrderProcessor
{
bool Process(string orderNumber);
}
public abstract class CustomerTypeOrderProcessor: IOrderProcessor
{
public bool Process(string orderNumber) => IsValid(orderNumber) ? ProcessOrder(orderNumber) : false;
protected abstract bool ProcessOrder(string orderNumber);
protected abstract bool IsValid(string orderNumber);
}
public class DirectCustomerOrderProcessor : CustomerTypeOrderProcessor
{
protected override bool IsValid(string orderNumber) => string.IsNullOrEmpty(orderNumber);
protected override bool ProcessOrder(string orderNumber) => true;
}
public class InDirectCustomerOrderProcessor : CustomerTypeOrderProcessor
{
protected override bool IsValid(string orderNumber) => orderNumber.StartsWith("EX");
protected override bool ProcessOrder(string orderNumber) => true;
}
public abstract class CustomerCategoryOrderProcessor : IOrderProcessor
{
public bool Process(string orderNumber) => ProcessOrder(GetDiscountPercentile(orderNumber), orderNumber);
protected abstract int GetDiscountPercentile(string orderNumber);
protected abstract bool ProcessOrder(int discount, string orderNumber);
}
public class GoldCustomer : CustomerCategoryOrderProcessor
{
protected override int GetDiscountPercentile(string orderNumber) => 15;
protected override bool ProcessOrder(int discount, string orderNumber) => true;
}
public class SilverCustomer : CustomerCategoryOrderProcessor
{
protected override int GetDiscountPercentile(string orderNumber) => 10;
protected override bool ProcessOrder(int discount, string orderNumber) => true;
}
public class OrderManager
{
private readonly IOrderProcessor _orderProcessor;// Not CustomerTypeOrderProcessor or CustomerCategoryOrderProcessor
//Using abstract class here would create problem as we have two different abstract classes
public OrderManager(IOrderProcessor orderProcessor) => _orderProcessor = orderProcessor;
}
À part la comparaison de Abstract class
avec Interface
, il est utile de comparer Abstract class
avec Concrete class
.
Utilisez une classe abstraite comme vous utilisez des classes concrètes juste sauf les moments où vous ne voulez pas/ne pouvez pas instancier les sans être étendus. Et créez les méthodes que vous ne voulez pas/ne pouvez pas implémenter de méthodes abstraites.
Si vous aimez l'analogie, pensez au chrome en tant que classe abstraite (vous ne pouvez pas l'utiliser comme navigateur, il ne peut donc pas être instancié), à chrome et à l'opéra en tant que classes concrètes dérivées de chrome et à la structure complémentaire du navigateur en tant qu'interface.
Interface:
Ne contient pas d'implémentations L'interface peut hériter de plusieurs interfaces (héritage multiple pris en charge) Les membres sont automatiquement publics Peut contenir des propriétés, méthodes, événements et indexeurs
Classe abstraite:
Peut/peut ne pas contenir des implémentations; Au moins un membre ne sera pas implémenté . Une classe peut hériter d'une seule classe de base; héritage multiple non autorisé . Les membres ont des modificateurs d'accès Peut contenir des champs, des propriétés, des constructeurs, des destructeurs, des méthodes, des événements et des indexeurs
Ce sont les principales différences entre la classe abstraite et les interfaces.
Ces réponses sont toutes trop longues.
Les interfaces servent à définir les comportements.
Les classes abstraites servent à définir une chose elle-même, y compris ses comportements. C'est pourquoi nous créons parfois une classe abstraite avec des propriétés supplémentaires héritant d'une interface.
Cela explique également pourquoi Java ne prend en charge que l'héritage unique pour les classes mais n'impose aucune restriction aux interfaces. Car un objet concret ne peut pas être différent des choses, mais il peut avoir des comportements différents.