Java n'autorise pas l'héritage multiple, mais il permet d'implémenter plusieurs interfaces. Pourquoi?
153
Java n'autorise pas l'héritage multiple, mais il permet d'implémenter plusieurs interfaces. Pourquoi?
Réponses:
Parce que les interfaces spécifient uniquement ce que fait la classe, pas comment elle le fait.
Le problème avec l'héritage multiple est que deux classes peuvent définir différentes manières de faire la même chose, et la sous-classe ne peut pas choisir laquelle choisir.
la source
Un de mes instructeurs de collège m'a expliqué cela de cette façon:
Donc, l'un des principaux problèmes est que si vous avez deux classes parentes, elles peuvent avoir des implémentations différentes de la même fonctionnalité - ou éventuellement deux fonctionnalités différentes avec le même nom, comme dans l'exemple de mon instructeur. Ensuite, vous devez décider lequel va utiliser votre sous-classe. Il existe des moyens de gérer cela, certainement - C ++ le fait - mais les concepteurs de Java ont estimé que cela compliquerait les choses.
Avec une interface, cependant, vous décrivez quelque chose que la classe est capable de faire, plutôt que d'emprunter la méthode d'une autre classe pour faire quelque chose. Plusieurs interfaces sont beaucoup moins susceptibles de provoquer des conflits délicats qui doivent être résolus que plusieurs classes parentes.
la source
Parce que l'héritage est surutilisé même si vous ne pouvez pas dire "hé, cette méthode semble utile, je vais aussi étendre cette classe".
la source
La réponse à cette question réside dans le fonctionnement interne du compilateur java (chaînage de constructeur). Si nous voyons le fonctionnement interne du compilateur java:
Après avoir compilé, cela ressemble à:
lorsque nous étendons la classe et en créons un objet, une chaîne de constructeur fonctionnera jusqu'à
Object
classe.Le code ci-dessus fonctionnera bien. mais si nous avons une autre classe appelée
Car
qui s'étendBank
et une classe hybride (héritage multiple) appeléeSBICar
:Dans ce cas (SBICar) ne parviendra pas à créer la chaîne de constructeur ( ambiguïté de compilation ).
Pour les interfaces, cela est autorisé car nous ne pouvons pas en créer un objet.
Pour le nouveau concept
default
et lastatic
méthode, veuillez vous référer à default dans l'interface .J'espère que cela résoudra votre requête. Merci.
la source
L'implémentation de plusieurs interfaces est très utile et ne pose pas beaucoup de problèmes aux développeurs de langage ni aux programmeurs. C'est donc permis. L'héritage multiple, tout en étant également utile, peut causer de graves problèmes aux utilisateurs ( diamant redouté de la mort ). Et la plupart des choses que vous faites avec l'héritage multiple peuvent également être effectuées par composition ou en utilisant des classes internes. L'héritage multiple est donc interdit car apportant plus de problèmes que de gains.
la source
ToyotaCar
et lesHybridCar
deux dérivaient deCar
et remplaçaientCar.Drive
, et s'ilsPriusCar
héritaient des deux mais ne les remplaceraient pasDrive
, le système n'aurait aucun moyen d'identifier ce que le virtuelCar.Drive
devrait faire. Les interfaces évitent ce problème en évitant la condition en italique ci-dessus.void UseCar(Car &foo)
; on ne peut pas s'attendre à ce qu'il inclue une désambiguïsation entreToyotaCar::Drive
etHybridCar::Drive
(car il ne devrait souvent ni savoir ni se soucier que ces autres types existent même ). Un langage pourrait, comme le fait C ++, exiger que le codeToyotaCar &myCar
souhaitant le transmettre àUseCar
doit d'abord être converti en soitHybridCar
ouToyotaCar
, mais puisque ((Car) (HybridCar) myCar) .Drive` et((Car)(ToyotaCar)myCar).Drive
ferait des choses différentes, cela impliquerait que les upcasts ne préservaient pas l’identité.Vous pouvez trouver une réponse précise pour cette requête dans la page de documentation d'Oracle sur l' héritage multiple
Héritage multiple d'état: possibilité d'hériter des champs de plusieurs classes
Si l'héritage multiple est autorisé et lorsque vous créez un objet en instanciant cette classe, cet objet hérite des champs de toutes les superclasses de la classe. Cela causera deux problèmes.
Héritage multiple d'implémentation: possibilité d'hériter des définitions de méthode de plusieurs classes
Problèmes avec cette approche: nommer les conflits et l' ambiguïté . Si une sous-classe et une superclasse contiennent le même nom de méthode (et la même signature), le compilateur ne peut pas déterminer la version à appeler.
Mais java prend en charge ce type d'héritage multiple avec les méthodes par défaut , qui ont été introduites depuis la version Java 8. Le compilateur Java fournit des règles pour déterminer la méthode par défaut utilisée par une classe particulière.
Reportez-vous au post SE ci-dessous pour plus de détails sur la résolution du problème de diamant:
Quelles sont les différences entre les classes abstraites et les interfaces dans Java 8?
Héritage multiple de type: Capacité d'une classe à implémenter plus d'une interface.
Comme l'interface ne contient pas de champs modifiables, vous n'avez pas à vous soucier des problèmes qui résultent de l'héritage multiple d'état ici.
la source
On dit que l'état des objets est référencé par rapport aux champs qu'il contient et qu'il deviendrait ambigu si trop de classes étaient héritées. Voici le lien
http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
la source
Java prend en charge l'héritage multiple via des interfaces uniquement. Une classe peut implémenter n'importe quel nombre d'interfaces mais ne peut étendre qu'une seule classe.
L'héritage multiple n'est pas pris en charge car il conduit à un problème de diamant mortel. Cependant, il peut être résolu mais cela conduit à un système complexe, de sorte que l'héritage multiple a été abandonné par les fondateurs de Java.
Dans un livre blanc intitulé «Java: un aperçu» de James Gosling en février 1995 ( lien ) donne une idée des raisons pour lesquelles l'héritage multiple n'est pas pris en charge en Java.
Selon Gosling:
la source
Pour la même raison, C # n'autorise pas l'héritage multiple mais vous permet d'implémenter plusieurs interfaces.
La leçon tirée du C ++ avec héritage multiple était qu'il conduisait à plus de problèmes qu'il n'en valait la peine.
Une interface est un contrat de choses que votre classe doit implémenter. Vous n'obtenez aucune fonctionnalité de l'interface. L'héritage vous permet d'hériter des fonctionnalités d'une classe parente (et en héritage multiple, cela peut devenir extrêmement déroutant).
Autoriser plusieurs interfaces vous permet d'utiliser des modèles de conception (comme Adapter) pour résoudre les mêmes types de problèmes que vous pouvez résoudre à l'aide de l'héritage multiple, mais d'une manière beaucoup plus fiable et prévisible.
la source
D1
et lesD2
deux héritent deB
, et chacun remplace une fonctionf
, et siobj
est une instance d'un typeS
qui hérite des deuxD1
etD2
mais ne remplace pasf
, alors la conversion d'une référence enS
enD1
devrait donner quelque chose dontf
utilise leD1
remplacement, et la conversion enB
ne devrait pas changez cela. De même, le cast d'une référenceS
versD2
devrait produire quelque chose dontf
utilise leD2
remplacement, et le cast versB
ne devrait pas changer cela. Si une langue n'avait pas besoin d'autoriser l'ajout de membres virtuels ...Puisque ce sujet n'est pas proche, je publierai cette réponse, j'espère que cela aidera quelqu'un à comprendre pourquoi java n'autorise pas l'héritage multiple.
Considérez la classe suivante:
Dans ce cas, la classe Abc ne prolonge rien non? Pas si vite, cette classe étend implicitement la classe Object, classe de base qui permet à tout de fonctionner en java. Tout est un objet.
Si vous essayez d'utiliser la classe ci - dessus , vous verrez que votre IDE vous permettent d'utiliser des méthodes telles que :
equals(Object o)
,toString()
, etc, mais vous ne l' avez pas déclaré ces méthodes, ils sont venus de la classe de baseObject
Tu pourrais essayer:
C'est bien, car votre classe ne s'étendra pas implicitement
Object
mais s'étendraString
parce que vous l'avez dit. Considérez le changement suivant:Maintenant, votre classe retournera toujours "hello" si vous appelez toString ().
Imaginez maintenant la classe suivante:
Encore une fois la classe
Flyer
implicite s'étend Object qui a la méthodetoString()
, n'importe quelle classe aura cette méthode puisqu'elles s'étendent toutesObject
indirectement, donc, si vous appelez àtoString()
partir deBird
, queltoString()
Java devrait utiliser? DeAbc
ouFlyer
? Cela se produira avec n'importe quelle classe qui essaie d'étendre deux classes ou plus, pour éviter ce genre de "collision de méthodes", ils ont construit l'idée d' interface , en gros vous pourriez les considérer comme une classe abstraite qui n'étend pas Object indirectement . Comme ils sont abstraits, ils devront être implémentés par une classe, ce qui est un objet(vous ne pouvez pas instancier une interface seule, ils doivent être implémentés par une classe), donc tout continuera à fonctionner correctement.Pour différer les classes des interfaces, le mot clé implements était réservé uniquement aux interfaces.
Vous pouvez implémenter n'importe quelle interface que vous aimez dans la même classe puisqu'elles n'étendent rien par défaut (mais vous pouvez créer une interface qui étend une autre interface, mais encore une fois, l'interface "père" n'étend pas Object "), donc une interface est juste une interface et ils ne souffriront pas de " colissions de signatures de méthodes ", s'ils le font, le compilateur vous lancera un avertissement et vous devrez juste changer la signature de la méthode pour la corriger (signature = nom de la méthode + paramètres + type de retour) .
la source
Parce qu'une interface n'est qu'un contrat. Et une classe est en fait un conteneur de données.
la source
Par exemple deux classes A, B ayant la même méthode m1 (). Et la classe C étend à la fois A, B.
Maintenant, la classe C recherchera la définition de m1. Tout d'abord, il cherchera en classe s'il n'a pas trouvé, puis il vérifiera la classe des parents. Les deux A, B ayant la définition Donc ici une ambiguïté se produit quelle définition doit choisir. Donc JAVA NE PREND PAS EN CHARGE DES HÉRITÉS MULTIPLES.
la source
Java ne prend pas en charge l'héritage multiple pour deux raisons:
Object
classe. Lorsqu'elle hérite de plus d'une super classe, la sous-classe obtient l'ambiguïté pour acquérir la propriété de la classe Object.super()
pour invoquer le constructeur de la classe supper. Si la classe a plus d'une super classe, elle devient confuse.Ainsi, lorsqu'une classe s'étend à partir de plus d'une super classe, nous obtenons une erreur de compilation.
la source
Prenons par exemple le cas où la classe A a une méthode getSomething et la classe B une méthode getSomething et la classe C étend A et B. Que se passerait-il si quelqu'un appelait C.getSomething? Il n'existe aucun moyen de déterminer la méthode à appeler.
Les interfaces spécifient simplement quelles méthodes une classe d'implémentation doit contenir. Une classe qui implémente plusieurs interfaces signifie simplement que la classe doit implémenter les méthodes de toutes ces interfaces. Whci n'entraînerait aucun problème comme décrit ci-dessus.
la source
Considérez un scénario où Test1, Test2 et Test3 sont trois classes. La classe Test3 hérite des classes Test2 et Test1. Si les classes Test1 et Test2 ont la même méthode et que vous l'appelez à partir d'un objet de classe enfant, il y aura ambiguïté pour appeler la méthode de la classe Test1 ou Test2, mais il n'y a pas d'ambiguïté pour l'interface car dans l'interface aucune implémentation n'est là.
la source
Java ne prend pas en charge l'héritage multiple, l'héritage multi-chemins et l'héritage hybride en raison d'un problème d'ambiguïté:
héritage multiple
la source
de manière simple, nous le savons tous, nous pouvons hériter (étendre) une classe, mais nous pouvons implémenter tellement d'interfaces ... c'est parce que dans les interfaces, nous ne donnons pas d'implémentation, disons simplement la fonctionnalité. supposons que si java peut étendre autant de classes et que celles-ci ont les mêmes méthodes .. à ce stade, si nous essayons d'appeler une méthode de super classe dans la sous-classe, quelle méthode suppose d'exécuter ??, le compilateur devient confus exemple: - essayez d'étendre plusieurs mais dans interfaces ces méthodes n'ont pas de corps, nous devrions les implémenter dans la sous-classe .. essayez plusieurs implémentations donc pas de soucis ..
la source
* C'est une réponse simple puisque je suis débutant en Java *
Considérez qu'il existe trois classes
X
,Y
etZ
.Nous héritons donc de
X extends Y, Z
And bothY
et avonsZ
une méthodealphabet()
avec le même type de retour et les mêmes arguments. Cette méthodealphabet()
enY
dit afficher premier alphabet et alphabet méthodeZ
dit affichage dernier alphabet . Alors, voici l'ambiguïté quandalphabet()
est appelé parX
. Que ce soit pour afficher le premier ou le dernier alphabet ??? Ainsi, java ne prend pas en charge l'héritage multiple. Dans le cas des interfaces, considérezY
etZ
comme des interfaces. Donc les deux contiendront la déclaration de méthodealphabet()
mais pas la définition. Il ne dira pas s'il faut afficher le premier alphabet ou le dernier alphabet ou quoi que ce soit, mais déclarera simplement une méthodealphabet()
. Il n'y a donc aucune raison de soulever l'ambiguïté. Nous pouvons définir la méthode avec tout ce que nous voulons dans la classeX
.Donc en un mot, dans Interfaces la définition se fait après implémentation donc pas de confusion.
la source