Dans une de mes interviews, on m'a demandé d'expliquer la différence entre une classe Interface et une classe Abstract .
Voici ma réponse:
Les méthodes d'une interface Java sont implicitement abstraites et ne peuvent pas avoir d'implémentations. Une classe abstraite Java peut avoir des méthodes d'instance qui implémentent un comportement par défaut.
Les variables déclarées dans une interface Java sont par défaut finales. Une classe abstraite peut contenir des variables non finales.
Les membres d'une interface Java sont publics par défaut. Une classe abstraite Java peut avoir les saveurs habituelles des membres de la classe comme privée, protégée, etc.
Une interface Java doit être implémentée à l'aide du mot clé «implements»; Une classe abstraite Java doit être étendue à l'aide du mot-clé «extend».
Une interface peut étendre une autre interface Java uniquement, une classe abstraite peut étendre une autre classe Java et implémenter plusieurs interfaces Java.
Une classe Java peut implémenter plusieurs interfaces mais elle ne peut étendre qu'une seule classe abstraite.
Cependant, l'intervieweur n'était pas satisfait et m'a dit que cette description représentait une " connaissance livresque ".
Il m'a demandé une réponse plus pratique, expliquant quand je choisirais une classe abstraite plutôt qu'une interface, en utilisant des exemples pratiques .
Où me suis-je trompé?
la source
Réponses:
Je vais d'abord vous donner un exemple:
Supposons que vous ayez 3 bases de données dans votre application. Ensuite, chaque implémentation de cette base de données doit définir les 2 méthodes ci-dessus:
Mais si
encryptPassword()
ne dépend pas de la base de données, et c'est la même chose pour chaque classe? Alors ce qui précède ne serait pas une bonne approche.Envisagez plutôt cette approche:
Désormais, dans chaque classe enfant, il nous suffit d'implémenter une seule méthode - la méthode qui dépend de la base de données.
la source
Rien n'est parfait dans ce monde. Ils s'attendaient peut-être davantage à une approche pratique.
Mais après votre explication, vous pouvez ajouter ces lignes avec une approche légèrement différente.
Les interfaces sont des règles (règles parce que vous devez leur donner une implémentation que vous ne pouvez pas ignorer ou éviter, afin qu'elles soient imposées comme des règles) qui fonctionne comme un document de compréhension commun entre les différentes équipes de développement logiciel.
Les interfaces donnent l'idée de ce qui doit être fait mais pas de la manière dont cela sera fait. L'implémentation dépend donc complètement du développeur en suivant les règles données (signifie la signature donnée des méthodes).
Les classes abstraites peuvent contenir des déclarations abstraites, des implémentations concrètes ou les deux.
Les déclarations abstraites sont comme des règles à suivre et des implémentations concrètes sont comme des directives (vous pouvez l'utiliser tel quel ou vous pouvez l'ignorer en remplaçant et en lui donnant votre propre implémentation).
De plus, quelles méthodes avec la même signature peuvent changer le comportement dans différents contextes sont fournies sous forme de déclarations d'interface comme règles à implémenter en conséquence dans différents contextes.
Edit: Java 8 facilite la définition de méthodes par défaut et statiques dans l'interface.
Désormais, lorsqu'une classe implémentera SomeInterface, il n'est pas obligatoire de fournir l'implémentation des méthodes d'interface par défaut.
Si nous avons une autre interface avec les méthodes suivantes:
Java n'autorise pas l'extension de plusieurs classes car cela entraîne le «problème Diamond» où le compilateur n'est pas en mesure de décider quelle méthode de superclasse utiliser. Avec les méthodes par défaut, le problème du diamant se posera également pour les interfaces. Parce que si une classe implémente les deux
et n'implémente pas la méthode par défaut commune, le compilateur ne peut pas décider laquelle choisir. Pour éviter ce problème, en java 8, il est obligatoire d'implémenter des méthodes par défaut communes à différentes interfaces. Si une classe implémente les deux interfaces ci-dessus, elle doit fournir l'implémentation de la méthode defaultMethod () sinon le compilateur générera une erreur de temps de compilation.
la source
Vous avez fait un bon résumé des différences pratiques d'utilisation et de mise en œuvre, mais vous n'avez rien dit sur la différence de sens.
Une interface est une description du comportement d'une classe d'implémentation. La classe d'implémentation garantit qu'elle disposera de ces méthodes qui pourront être utilisées dessus. Il s'agit essentiellement d'un contrat ou d'une promesse que la classe doit faire.
Une classe abstraite est une base pour différentes sous-classes qui partagent un comportement qui n'a pas besoin d'être créé à plusieurs reprises. Les sous-classes doivent terminer le comportement et avoir la possibilité de remplacer le comportement prédéfini (tant qu'il n'est pas défini comme
final
ouprivate
).Vous trouverez de bons exemples dans le
java.util
paquet qui comprend des interfaces commeList
et des classes abstraites commeAbstractList
qui implémentent déjà l'interface. La documentation officielle décrit les élémentsAbstractList
suivants:la source
abstract
mot-clé, c'est-à-dire lorsqu'un compilateur voit cela, il le sait, les informations suivantes sont incomplètes et doivent être implémentées . Les interfaces sont toujours incomplètes, mais les classes abstraites sont abstraites car elles devaient avoir desincomplete (abstract)
méthodes.Une interface se compose de variables singleton (final statique public) et de méthodes abstraites publiques. Nous préférons normalement utiliser une interface en temps réel lorsque nous savons quoi faire mais ne savons pas comment le faire .
Ce concept peut être mieux compris par l'exemple:
Considérez une classe de paiement. Le paiement peut être effectué de plusieurs manières, comme PayPal, carte de crédit, etc. Nous prenons donc normalement le paiement comme interface qui contient une
makePayment()
méthode et CreditCard et PayPal sont les deux classes d'implémentation.Dans l'exemple ci-dessus, CreditCard et PayPal sont deux classes / stratégies d'implémentation. Une interface nous permet également le concept d'héritage multiple en Java qui ne peut pas être accompli par une classe abstraite.
Nous choisissons une classe abstraite lorsqu'il existe des fonctionnalités pour lesquelles nous savons quoi faire et d'autres fonctionnalités que nous savons comment exécuter .
Prenons l'exemple suivant:
Si nous ajoutons des méthodes (concrètes / abstraites) à l'avenir à une classe abstraite donnée, alors la classe d'implémentation n'aura pas besoin de changer son code. Cependant, si nous ajoutons des méthodes dans une interface à l'avenir, nous devons ajouter des implémentations à toutes les classes qui ont implémenté cette interface, sinon des erreurs de compilation se produisent.
Il y a d'autres différences, mais ce sont les principales qui pourraient être ce à quoi votre intervieweur s'attendait. J'espère que cela a été utile.
la source
interface
etabstract class
.Différence entre la classe Abstact et l'interface
Méthodes par défaut de l'interface dans Java 8
Méthode statique de l'interface Java
Interfaces fonctionnelles Java
Classes abstraites et interfaces dans Java 8
Différence conceptuelle:
Les classes abstraites sont valables pour les implémentations squelettiques (c'est-à-dire partielles) des interfaces mais ne devraient pas exister sans interface correspondante.
Ainsi, lorsque les classes abstraites sont effectivement réduites pour être des implémentations squelettiques d'interfaces à faible visibilité, les méthodes par défaut peuvent-elles également supprimer cela? Décidément: Non! L'implémentation d'interfaces nécessite presque toujours une partie ou la totalité de ces outils de création de classe qui manquent aux méthodes par défaut. Et si une interface ne fonctionne pas, c'est clairement un cas spécial, qui ne devrait pas vous induire en erreur.
Méthodes par défaut de l'interface dans Java 8
Java 8 présente la « méthode par défaut » ou (méthodes Defender), qui permet au développeur d'ajouter de nouvelles méthodes aux interfaces sans interrompre l'implémentation existante de ces interfaces. Il offre une flexibilité permettant à l'interface de définir l'implémentation qui sera utilisée par défaut dans le cas où une classe concrète ne fournira pas d'implémentation pour cette méthode.
Prenons un petit exemple pour comprendre comment cela fonctionne:
La classe suivante se compilera avec succès dans Java JDK 8,
Si vous créez une instance de OldInterfaceImpl:
Méthode par défaut:
Des méthodes par défaut peuvent être fournies à une interface sans affecter les classes d'implémentation car elle inclut une implémentation. Si chaque méthode ajoutée dans une interface définie avec implémentation, aucune classe d'implémentation n'est affectée. Une classe d'implémentation peut remplacer l'implémentation par défaut fournie par l'interface.
Lorsque nous étendons une interface qui contient une méthode par défaut, nous pouvons effectuer ce qui suit,
Erreur de compilation de la méthode ForEach résolue à l'aide de la méthode par défaut
Pour Java 8, les collections JDK ont été étendues et la méthode forEach est ajoutée à la collection entière (qui fonctionne en conjonction avec lambdas). De manière conventionnelle, le code ressemble à ci-dessous,
Étant donné que cela entraîne chaque classe d'implémentation avec des erreurs de compilation par conséquent, une méthode par défaut a été ajoutée avec une implémentation requise afin que l'implémentation existante ne soit pas modifiée.
L'interface itérable avec la méthode par défaut est ci-dessous,
Le même mécanisme a été utilisé pour ajouter Stream dans l'interface JDK sans rompre les classes d'implémentation.
Méthode par défaut et problèmes d'ambiguïté d'héritage multiples
Étant donné que java Class peut implémenter plusieurs interfaces et que chaque interface peut définir une méthode par défaut avec la même signature de méthode, les méthodes héritées peuvent donc entrer en conflit les unes avec les autres.
Considérez l'exemple ci-dessous,
Le code ci-dessus ne parviendra pas à compiler avec l'erreur suivante,
Afin de corriger cette classe, nous devons fournir une implémentation de méthode par défaut:
De plus, si nous voulons invoquer l'implémentation par défaut fournie par l'une des super interfaces plutôt que notre propre implémentation, nous pouvons le faire comme suit,
Nous pouvons choisir n'importe quelle implémentation par défaut ou les deux dans le cadre de notre nouvelle méthode.
Points importants sur les méthodes par défaut de l'interface java:
Lien de ressource:
Méthode statique de l'interface Java
Java Interface Static Method, exemple de code, méthode statique vs méthode par défaut
La méthode statique de l'interface Java est similaire à la méthode par défaut, sauf que nous ne pouvons pas les remplacer dans les classes d'implémentation. Cette fonctionnalité nous aide à éviter les résultats indésirables en cas de mauvaise implémentation dans les classes d'implémentation. Examinons cela avec un exemple simple.
Voyons maintenant une classe d'implémentation qui a la méthode isNull () avec une mauvaise implémentation.
Notez que isNull (String str) est une méthode de classe simple, elle ne remplace pas la méthode d'interface. Par exemple, si nous ajoutons une annotation @Override à la méthode isNull (), cela entraînera une erreur de compilation.
Maintenant, lorsque nous exécuterons l'application, nous obtenons la sortie suivante.
Si nous faisons la méthode d'interface de statique à par défaut, nous obtiendrons la sortie suivante.
La méthode statique d'interface Java n'est visible que pour les méthodes d'interface, si nous supprimons la méthode isNull () de la classe MyDataImpl, nous ne pourrons pas l'utiliser pour l'objet MyDataImpl. Cependant, comme d'autres méthodes statiques, nous pouvons utiliser des méthodes statiques d'interface en utilisant le nom de classe. Par exemple, une déclaration valide sera:
Points importants sur la méthode statique de l'interface java:
Interfaces fonctionnelles Java
Avant de conclure le message, je voudrais fournir une brève introduction aux interfaces fonctionnelles. Une interface avec exactement une méthode abstraite est connue sous le nom d'interface fonctionnelle.
Une nouvelle annotation
@FunctionalInterface
a été introduite pour marquer une interface comme interface fonctionnelle.@FunctionalInterface
l'annotation est un moyen d'éviter l'ajout accidentel de méthodes abstraites dans les interfaces fonctionnelles. Il est facultatif mais bon de l'utiliser.Les interfaces fonctionnelles sont une fonctionnalité attendue depuis longtemps et très recherchée de Java 8 car elle nous permet d'utiliser des expressions lambda pour les instancier. Un nouveau package java.util.function avec un tas d'interfaces fonctionnelles est ajouté pour fournir des types cibles pour les expressions lambda et les références de méthode. Nous étudierons les interfaces fonctionnelles et les expressions lambda dans les prochains articles.
Emplacement des ressources:
la source
Toutes vos déclarations sont valables à l'exception de votre première déclaration (après la version Java 8):
Depuis la page de documentation :
Méthodes par défaut:
Une interface peut avoir des méthodes par défaut , mais sont différentes des méthodes abstraites dans les classes abstraites.
Lorsque vous étendez une interface qui contient une méthode par défaut, vous pouvez effectuer les opérations suivantes:
abstract
.Méthodes statiques:
En plus des méthodes par défaut, vous pouvez définir des méthodes statiques dans les interfaces. (Une méthode statique est une méthode associée à la classe dans laquelle elle est définie plutôt qu'à tout objet. Chaque instance de la classe partage ses méthodes statiques.)
Cela vous permet d'organiser plus facilement les méthodes d'assistance dans vos bibliothèques;
Exemple de code de la page de documentation sur les méthodes et
interface
avoir .static
default
Utilisez les instructions ci-dessous pour choisir d'utiliser une interface ou une classe abstraite.
Interface:
Classe abstraite:
Partagez le code entre plusieurs classes étroitement liées. Elle établit une relation.
Partager l'état commun entre les classes liées (l'état peut être modifié dans des classes concrètes)
Articles Similaires:
Interface vs classe abstraite (OO général)
Implémente vs étend: Quand l'utiliser? Quelle est la différence?
En parcourant ces exemples, vous pouvez comprendre que
Les classes non liées peuvent avoir des capacités via l'interface, mais les classes liées modifient le comportement par l'extension des classes de base.
la source
stateless
interface est un joli succès. L'interface ne peut avoir aucun état (l'interface peut avoir des constantes mais elles sont finales / statiques donc immuables).Votre explication semble décente, mais peut-être semble-t-il que vous lisiez tout cela dans un manuel? : - /
Ce qui me dérange le plus, c'est à quel point votre exemple était solide? Avez-vous pris la peine d'inclure presque toutes les différences entre l'abstrait et les interfaces?
Personnellement, je suggère ce lien: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE
pour une liste exhaustive des différences ..
J'espère que cela vous aidera, vous et tous les autres lecteurs, dans leurs futures interviews
la source
De nombreux développeurs juniors font l'erreur de considérer les interfaces, les classes abstraites et concrètes comme de légères variations de la même chose, et choisissent l'une d'entre elles uniquement pour des raisons techniques: ai-je besoin d'un héritage multiple? Ai-je besoin d'un endroit pour mettre des méthodes communes? Dois-je m'embêter avec autre chose qu'un cours concret? C'est faux, et le problème principal est caché dans ces questions: "Je" . Lorsque vous écrivez du code pour vous-même, vous pensez rarement à d'autres développeurs actuels ou futurs travaillant sur ou avec votre code.
Les interfaces et les classes abstraites, bien qu'apparemment similaires d'un point de vue technique, ont des significations et des objectifs complètement différents.
Sommaire
Une interface définit un contrat qu'une certaine implémentation remplira pour vous .
Une classe abstraite fournit un comportement par défaut que votre implémentation peut réutiliser.
Ces deux points ci-dessus sont ce que je recherche lors d'un entretien, et c'est un résumé assez compact. Lire la suite pour plus de détails.
Résumé alternatif
Par exemple
En d'autres termes: une classe concrète fait le travail réel, d'une manière très spécifique. Par exemple, un utilise des nœuds à double liaison pour stocker une liste d'objets, qui offre à la place une itération rapide, des modifications sur place et une insertion / suppression / addition, mais est terrible à l'accès aléatoire. Ces deux types de listes sont optimisés pour différents cas d'utilisation, et la façon dont vous allez les utiliser importe beaucoup. Lorsque vous essayez d'extraire les performances d'une liste avec laquelle vous interagissez fortement, et lorsque vous choisissez le type de liste, vous devez soigneusement choisir celle que vous instanciez.
ArrayList
utilise une zone de mémoire contiguë pour stocker une liste d'objets de manière compacte qui offre un accès aléatoire rapide, une itération et des modifications sur place, mais est terrible lors des insertions, des suppressions et parfois même des ajouts; pendant ce temps, unLinkedList
D'un autre côté, les utilisateurs de haut niveau d'une liste ne se soucient pas vraiment de la façon dont elle est réellement mise en œuvre, et ils doivent être isolés de ces détails. Imaginons que Java n'ait pas exposé l'
List
interface, mais n'avait qu'uneList
classe concrète qui est en fait ce quiLinkedList
est en ce moment. Tous les développeurs Java auraient adapté leur code pour s'adapter aux détails de l'implémentation: éviter l'accès aléatoire, ajouter un cache pour accélérer l'accès, ou simplement réimplémenterArrayList
par eux-mêmes, bien qu'il soit incompatible avec tous les autres codes qui ne fonctionnent qu'avecList
. Ce serait terrible ... Mais imaginez maintenant que les maîtres Java réalisent réellement qu'une liste chaînée est terrible pour la plupart des cas d'utilisation réels, et ont décidé de passer à une liste de tableaux pour leur seulList
classe disponible. Cela affecterait les performances de chaque programme Java dans le monde, et les gens n'en seraient pas satisfaits. Et le principal coupable est que les détails de l'implémentation étaient disponibles, et les développeurs ont supposé que ces détails étaient un contrat permanent sur lequel ils pouvaient s'appuyer. C'est pourquoi il est important de masquer les détails de l'implémentation et de définir uniquement un contrat abstrait. C'est le but d'une interface: définir le type d'entrée qu'une méthode accepte et le type de sortie attendu, sans exposer tous les tripes qui inciteraient les programmeurs à modifier leur code pour s'adapter aux détails internes qui pourraient changer avec toute mise à jour future .Une classe abstraite se situe entre les interfaces et les classes concrètes. Il est censé aider les implémentations à partager du code commun ou ennuyeux. Par exemple,
AbstractCollection
fournit des implémentations deisEmpty
base pour basées sur la taille est 0,contains
comme itérer et comparer,addAll
comme répétéadd
, et ainsi de suite. Cela permet aux implémentations de se concentrer sur les parties cruciales qui les différencient: comment réellement stocker et récupérer des données.Autre perspective: API versus SPI
Les interfaces sont des passerelles à faible cohésion entre différentes parties du code. Ils permettent aux bibliothèques d'exister et d'évoluer sans casser chaque utilisateur de bibliothèque lorsque quelque chose change en interne. C'est ce qu'on appelle l' interface de programmation d'application , pas les classes de programmation d'application. À plus petite échelle, ils permettent également à plusieurs développeurs de collaborer avec succès sur des projets à grande échelle, en séparant différents modules via des interfaces bien documentées.
Les classes abstraites sont des aides à haute cohésion à utiliser lors de l'implémentation d'une interface, en supposant un certain niveau de détails d'implémentation. Alternativement, des classes abstraites sont utilisées pour définir des SPI, des interfaces de fournisseur de services.
La différence entre une API et un SPI est subtile, mais importante: pour une API, l'accent est mis sur qui l' utilise et pour un SPI, l'accent est mis sur qui l' implémente .
L'ajout de méthodes à une API est facile, tous les utilisateurs existants de l'API seront toujours compilés. L'ajout de méthodes à un SPI est difficile, car chaque fournisseur de services (implémentation concrète) devra implémenter les nouvelles méthodes. Si des interfaces sont utilisées pour définir un SPI, un fournisseur devra publier une nouvelle version chaque fois que le contrat SPI change. Si des classes abstraites sont utilisées à la place, de nouvelles méthodes pourraient être définies en termes de méthodes abstraites existantes, ou en tant que
throw not implemented exception
stubs vides , ce qui permettra au moins à une ancienne version d'une implémentation de service de se compiler et de s'exécuter.Une note sur Java 8 et les méthodes par défaut
Bien que Java 8 ait introduit des méthodes par défaut pour les interfaces, ce qui rend la ligne entre les interfaces et les classes abstraites encore plus floue, ce n'était pas pour que les implémentations puissent réutiliser le code, mais pour faciliter la modification des interfaces qui servent à la fois d'API et de SPI (ou sont mal utilisés pour définir des SPI au lieu de classes abstraites).
"Connaissance du livre"
Les détails techniques fournis dans la réponse du PO sont considérés comme des "connaissances du livre" car c'est généralement l'approche utilisée à l'école et dans la plupart des livres de technologie sur une langue: ce qu'est une chose, pas comment l' utiliser dans la pratique, en particulier dans les applications à grande échelle .
Voici une analogie: supposé que la question était:
La réponse technique ressemble à:
C'est vrai, mais il manque complètement les points qu'il s'agit de deux choses complètement différentes, et les deux peuvent être utilisées en même temps à des fins différentes, et l'aspect "le faire" n'est pas la chose la plus importante à propos de l'une ou l'autre des deux options . La réponse manque de perspective, elle montre une façon de penser immature, tout en présentant correctement les vrais "faits".
la source
Qu'en est-il de penser de la manière suivante:
Donc, quand vous avez une classe abstraite Mammifères, une sous-classe Humaine et une interface Conduite, alors vous pouvez dire
Ma suggestion est que la phrase de connaissance du livre indique qu'il voulait entendre la différence sémantique entre les deux (comme d'autres l'ont déjà suggéré ici).
la source
Une interface est un "contrat" où la classe qui implémente le contrat promet d'implémenter les méthodes. Un exemple où j'ai dû écrire une interface au lieu d'une classe était quand je mettais à jour un jeu de 2D à 3D. J'ai dû créer une interface pour partager des cours entre la version 2D et la version 3D du jeu.
Ensuite, je peux implémenter les méthodes basées sur l'environnement, tout en étant capable d'appeler ces méthodes à partir d'un objet qui ne sait pas quelle version du jeu se charge.
public class Adventure extends JFrame implements Playable
public class Dungeon3D extends SimpleApplication implements Playable
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
En règle générale, dans le monde du jeu, le monde peut être une classe abstraite qui exécute des méthodes sur le jeu:
la source
Les classes abstraites ne sont pas de l'abstraction pure, car sa collection de méthodes concrètes (implémentées) et non implémentées. Mais les interfaces sont une pure abstraction car il n'existe que des méthodes non implémentées et non des méthodes concrètes.
Pourquoi des classes abstraites?
Pourquoi des interfaces?
la source
Une interface est comme un ensemble de gènes qui sont publiquement documentés pour avoir une sorte d'effet: un test ADN me dira si je les ai - et si je le fais, je peux faire savoir publiquement que je suis un "porteur" "et une partie de mon comportement ou de mon état s'y conformera. (Mais bien sûr, je peux avoir de nombreux autres gènes qui fournissent des traits hors de cette portée.)
Une classe abstraite est comme l'ancêtre mort d'une espèce de sexe unique (*): elle ne peut pas être vivifiée mais vivante (c'est -à- dire non abstraite descendant ) hérite de tous ses gènes.
(*) Pour étirer cette métaphore, disons que tous les membres de l'espèce vivent au même âge. Cela signifie que tous les ancêtres d'un ancêtre mort doivent également être morts - et de même, tous les descendants d'un ancêtre vivant doivent être vivants.
la source
Je fais des entretiens pour le travail et je regarderais aussi défavorablement votre réponse (désolé mais je suis très honnête). Il semble que vous ayez lu la différence et révisé une réponse, mais vous ne l'avez peut-être jamais utilisé dans la pratique.
Une bonne explication de la raison pour laquelle vous utiliseriez chacun peut être bien meilleure que d'avoir une explication précise de la différence. Les employeurs veulent ultimement que les programmeurs fassent des choses qu'ils ne connaissent pas, ce qui peut être difficile à démontrer lors d'une entrevue. La réponse que vous avez donnée serait bonne si vous postulez pour un emploi technique ou basé sur la documentation, mais pas pour un rôle de développeur.
Bonne chance avec des interviews à l'avenir.
De plus, ma réponse à cette question concerne davantage la technique d'entrevue que le matériel technique que vous avez fourni. Pensez peut-être à lire à ce sujet. https://workplace.stackexchange.com/ peut être un excellent endroit pour ce genre de chose.
la source
Vous choisissez Interface en Java pour éviter le problème Diamond dans l'héritage multiple .
Si vous souhaitez que toutes vos méthodes soient implémentées par votre client, optez pour l'interface. Cela signifie que vous concevez l'intégralité de l'application sur abstract.
Vous choisissez la classe abstraite si vous savez déjà ce qui est commun. Par exemple, prenez un cours abstrait
Car
. À un niveau supérieur, vous implémentez les méthodes de voiture courantes commecalculateRPM()
. C'est une méthode courante et vous laissez le client implémenter son propre comportement commecalculateMaxSpeed()
etc. Vous auriez probablement expliqué en donnant quelques exemples en temps réel que vous avez rencontrés dans votre travail quotidien.la source
Une interface est purement abstraite. nous n'avons aucun code d'implémentation dans l'interface.
La classe abstraite contient les deux méthodes et son implémentation.
cliquez ici pour regarder le tutoriel sur les interfaces et les classes abstraites
la source
La principale différence que j'ai observée est que la classe abstraite nous fournit un comportement commun déjà implémenté et que les sous-classes n'ont besoin que d'implémenter des fonctionnalités spécifiques qui leur correspondent. où, comme pour une interface, ne précisera que les tâches à effectuer et aucune implémentation ne sera donnée par l'interface. Je peux dire qu'il spécifie le contrat entre lui-même et les classes implémentées.
la source
Même moi, j'ai été confronté à la même question dans plusieurs interviews et croyez-moi, cela rend votre temps misérable pour convaincre l'intervieweur. Si j'inhérente à toutes les réponses ci-dessus, je dois ajouter un point clé de plus pour le rendre plus convaincant et utiliser OO à son meilleur.
Dans le cas où vous ne prévoyez pas de modification des règles , pour la sous-classe à suivre, pour un long avenir, optez pour l'interface, car vous ne pourrez pas y modifier et si vous le faites, vous devez opter pour le changements dans toutes les autres sous-classes, alors que, si vous pensez, vous voulez réutiliser la fonctionnalité, définir certaines règles et la rendre ouverte à la modification , optez pour la classe Abstract.
Pensez de cette façon, vous avez utilisé un service de consommables ou vous avez fourni du code au monde et vous avez la possibilité de modifier quelque chose, supposez un contrôle de sécurité Et si je suis un consommateur du code et Un matin après une mise à jour, je trouver toutes les marques de lecture dans mon Eclipse, toute l'application est en panne. Donc, pour éviter de tels cauchemars, utilisez Résumé sur les interfaces
Je pense que cela pourrait convaincre l'enquêteur dans une certaine mesure ... Bonne entrevues à venir.
la source
Lorsque j'essaie de partager le comportement entre 2 classes étroitement liées, je crée une classe abstraite qui détient le comportement commun et sert de parent aux deux classes.
Lorsque j'essaie de définir un type, une liste de méthodes qu'un utilisateur de mon objet peut invoquer de manière fiable, je crée une interface.
Par exemple, je ne créerais jamais une classe abstraite avec 1 sous-classe concrète car les classes abstraites concernent le partage des comportements. Mais je pourrais très bien créer une interface avec une seule implémentation. L'utilisateur de mon code ne saura pas qu'il n'y a qu'une seule implémentation. En effet, dans une future version, il peut y avoir plusieurs implémentations, qui sont toutes des sous-classes d'une nouvelle classe abstraite qui n'existaient même pas lorsque j'ai créé l'interface.
Cela aurait pu sembler un peu trop livresque aussi (même si je ne l'ai jamais vu s'exprimer ainsi partout où je me souviens). Si l'intervieweur (ou l'OP) voulait vraiment plus de mon expérience personnelle à ce sujet, j'aurais été prêt avec des anecdotes d'une interface qui a évolué par nécessité et vice versa.
Encore une chose. Java 8 vous permet désormais de mettre du code par défaut dans une interface, brouillant davantage la frontière entre les interfaces et les classes abstraites. Mais d'après ce que j'ai vu, cette fonctionnalité est surutilisée même par les créateurs des bibliothèques de base Java. Cette fonctionnalité a été ajoutée, à juste titre, pour permettre d'étendre une interface sans créer d'incompatibilité binaire. Mais si vous créez un tout nouveau type en définissant une interface, alors l'interface devrait être JUSTE une interface. Si vous souhaitez également fournir du code commun, créez par tous les moyens une classe d'assistance (abstraite ou concrète). N'encombrez pas votre interface depuis le début avec des fonctionnalités que vous voudrez peut-être modifier.
la source
La différence de base entre l'interface et la classe abstraite est que l'interface prend en charge l'héritage multiple mais pas la classe abstraite.
Dans la classe abstraite, vous pouvez également fournir toutes les méthodes abstraites comme l'interface.
pourquoi la classe abstraite est requise?
Dans certains scénarios, lors du traitement de la demande de l'utilisateur, la classe abstraite ne sait pas quelle intention de l'utilisateur. Dans ce scénario, nous définirons une méthode abstraite dans la classe et demanderons à l'utilisateur qui étend cette classe, veuillez indiquer votre intention dans la méthode abstraite. Dans ce cas, les classes abstraites sont très utiles
Pourquoi une interface est-elle requise?
Disons que j'ai un travail que je n'ai pas d'expérience dans ce domaine. Par exemple, si vous voulez construire un bâtiment ou un barrage, que ferez-vous dans ce scénario?
Ici, je ne me soucie pas de la façon dont ils ont construit. L'objet final a satisfait ou non mes exigences, c'est seulement mon point clé.
Ici, vos exigences appelées interface et constructeurs sont appelées implémenteur.
la source
En quelques mots, je répondrais de cette façon:
Les classes abstraites peuvent être traitées comme quelque chose entre ces deux cas (cela introduit un certain état mais vous oblige également à définir un comportement), une classe entièrement abstraite est une interface (il s'agit d'un développement ultérieur de classes constituées de méthodes virtuelles uniquement en C ++ comme autant que je sache sa syntaxe).
Bien sûr, à partir de Java 8, les choses ont légèrement changé, mais l'idée est toujours la même.
Je suppose que c'est assez pour une interview Java typique, si vous n'êtes pas interviewé par une équipe de compilation.
la source
D'après ce que je comprends, une interface, qui est composée de variables finales et de méthodes sans implémentations, est implémentée par une classe pour obtenir un groupe de méthodes ou de méthodes qui sont liées les unes aux autres. D'un autre côté, une classe abstraite, qui peut contenir des variables et des méthodes non finales avec des implémentations, est généralement utilisée comme guide ou comme super-classe dont toutes les classes apparentées ou similaires héritent. En d'autres termes, une classe abstraite contient toutes les méthodes / variables qui sont partagées par toutes ses sous-classes.
la source
En classe abstraite, vous pouvez écrire l'implémentation par défaut des méthodes! Mais dans Interface, vous ne pouvez pas. Fondamentalement, dans l'interface, il existe des méthodes virtuelles pures qui doivent être implémentées par la classe qui implémente l'interface.
la source
Oui, vos réponses étaient techniquement correctes, mais là où vous vous êtes trompé, vous ne leur montriez pas que vous compreniez les avantages et les inconvénients de choisir l'un plutôt que l'autre. En outre, ils étaient probablement préoccupés / paniqués par la compatibilité de leur base de code avec les mises à niveau à l'avenir. Ce type de réponse a peut-être aidé (en plus de ce que vous avez dit):
Bonne chance pour votre prochaine interview!
la source
Je vais essayer de répondre en utilisant un scénario pratique pour montrer la distinction entre les deux.
Les interfaces sont livrées avec une charge utile nulle, c'est-à-dire qu'aucun état ne doit être maintenu et sont donc un meilleur choix pour simplement associer un contrat (capacité) à une classe.
Par exemple, disons que j'ai une classe Task qui exécute une action, maintenant pour exécuter une tâche dans un thread séparé, je n'ai pas vraiment besoin d'étendre la classe Thread. ), puis passez l'objet de cette classe Task à une instance de thread et appelez sa méthode start ().
Eh bien, techniquement, c'était possible, mais au niveau de la conception, cela aurait été un mauvais choix étant:
En d'autres termes, la classe Task avait besoin d'une capacité à exécuter dans un thread, ce qu'elle a obtenu en implémentant des versets d'interface Runnable étendant la classe Thread qui en ferait un thread.
Avertissement: un exemple stupide suit, essayez de ne pas juger :-P
Maintenant, on vous a donné le choix d’être semblable à Dieu, mais vous pouvez choisir d’être Pardonneur uniquement (c’est-à-dire pas semblable à Dieu) et de faire:
Ou vous pouvez choisir d'être comme Dieu et faire:
PS avec interface java 8 peut également avoir des méthodes statiques ainsi que par défaut (implémentation redéfinissable) et donc l'interface différence n / b et la classe abstraite sont encore plus restreintes.
la source
Presque tout semble déjà être couvert ici .. Ajout d'un autre point sur la mise en œuvre pratique de la
abstract
classe:la source
hmm maintenant les gens ont faim approche pratique, vous avez tout à fait raison mais la plupart des enquêteurs regardent selon leurs exigences actuelles et veulent une approche pratique.
après avoir terminé votre réponse, vous devriez sauter sur l'exemple:
Abstrait:
par exemple, nous avons une fonction de salaire qui a des paramètres communs à tous les employés. Ensuite, nous pouvons avoir une classe abstraite appelée CTC avec un corps de méthode partiellement défini et elle sera étendue par tous les types d'employés et redéfinie selon leurs capacités supplémentaires. Pour la fonctonalité commune.
Interface
l'interface en java permet d'avoir des fonctionnalités interfcae sans étendre celle-ci et il faut être clair avec l'implémentation de la signature des fonctionnalités que l'on souhaite introduire dans son application. cela vous obligera à avoir une définition. Pour différentes fonctionnalités.
vous pouvez aussi avoir une telle activité forcée avec une classe abstraite par des méthgos définis comme abstraits, maintenant une classe qui étend la classe abstraite remin abstraite jusqu'à ce qu'elle écrase cette fonction abstraite.
la source
D'après ce que je comprends et comment j'approche,
L'interface est comme une spécification / contrat, toute classe qui implémente une classe d'interface doit implémenter toutes les méthodes définies dans la classe abstraite (sauf les méthodes par défaut (introduites dans Java 8))
Alors que je définis un résumé de classe quand je connais l'implémentation requise pour certaines méthodes de la classe et certaines méthodes, je ne sais toujours pas quelle sera l'implémentation (nous pouvons connaître la signature de la fonction mais pas l'implémentation). Je le fais pour que plus tard dans la partie du développement, quand je saurai comment ces méthodes doivent être implémentées, je puisse simplement étendre cette classe abstraite et implémenter ces méthodes.
Remarque: Vous ne pouvez pas avoir de corps de fonction dans les méthodes d'interface sauf si la méthode est statique ou par défaut.
la source
Je crois que l'intervieweur essayait de comprendre la différence entre l'interface et la mise en œuvre.
L'interface - pas une interface Java, mais «interface» en termes plus généraux - avec un module de code est, fondamentalement, le contrat conclu avec le code client qui utilise l'interface.
L'implémentation d'un module de code est le code interne qui fait fonctionner le module. Souvent, vous pouvez implémenter une interface particulière de plusieurs manières différentes et même modifier l'implémentation sans que le code client ne soit au courant du changement.
Une interface Java ne doit être utilisée qu'en tant qu'interface dans le sens générique ci-dessus, pour définir comment la classe se comporte au profit du code client utilisant la classe, sans spécifier aucune implémentation. Ainsi, une interface comprend des signatures de méthode - les noms, les types de retour et les listes d'arguments - pour les méthodes censées être appelées par le code client, et devrait en principe avoir beaucoup de Javadoc pour chaque méthode décrivant ce que fait cette méthode. La raison la plus convaincante d'utiliser une interface est que vous prévoyez d'avoir plusieurs implémentations différentes de l'interface, peut-être en sélectionnant une implémentation en fonction de la configuration de déploiement.
Une classe abstraite Java, en revanche, fournit une implémentation partielle de la classe, plutôt que d'avoir un objectif principal de spécifier une interface. Il doit être utilisé lorsque plusieurs classes partagent du code, mais lorsque les sous-classes sont également censées fournir une partie de l'implémentation. Cela permet au code partagé d'apparaître en un seul endroit - la classe abstraite - tout en précisant que des parties de l'implémentation ne sont pas présentes dans la classe abstraite et devraient être fournies par des sous-classes.
la source
votre réponse est juste, mais l'intervieweur a besoin de vous pour différencier selon la perspective de l'ingénierie logicielle et non selon les détails de Java.
Mots simples:
Une interface est comme l'interface d'une boutique, tout ce qui y est affiché devrait être là dans la boutique, donc toute méthode dans l'interface doit être implémentée dans la classe concrète. Maintenant, que se passe-t-il si certaines classes partagent certaines méthodes exactes et varient dans d'autres. Supposons que l'Interface concerne un magasin qui contient deux choses et supposons que nous avons deux magasins qui contiennent tous les deux des équipements de sport, mais l'un a des vêtements supplémentaires et l'autre des chaussures supplémentaires. Donc ce que vous faites est de créer une classe abstraite pour le sport qui implémente la méthode Sports et laisse l'autre méthode non implémentée. La classe abstraite signifie ici que cette boutique n'existe pas elle-même mais c'est la base pour d'autres classes / boutiques. De cette façon, vous organisez le code, évitez les erreurs de réplication du code, unifiez le code et garantissez la réutilisation par une autre classe.
la source