Java n'autorise pas l'héritage multiple, mais permet l'implémentation de plusieurs interfaces. Pourquoi?
Parce que les interfaces spécifient seulement quoi la classe est en train de le faire, 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.
Un de mes professeurs d'université m'a expliqué ça de cette façon:
Supposons que j'ai une classe, qui est un grille-pain, et une autre classe, qui est NuclearBomb. Ils pourraient tous les deux avoir un réglage "d'obscurité". Ils ont tous deux une méthode on (). (L'un a un off (), l'autre pas.) Si je veux créer une classe qui est une sous-classe de ces deux ... comme vous pouvez le voir, c'est un problème qui pourrait vraiment exploser dans mon visage ici .
Ainsi, l'un des problèmes principaux est que si vous avez deux classes parentes, elles peuvent avoir différentes implémentations de la même fonctionnalité - ou éventuellement deux fonctionnalités différentes portant le même nom, comme dans l'exemple de mon instructeur. Ensuite, vous devez décider laquelle de votre sous-classe va utiliser. Il y a des façons de gérer cela, certes - C++ le fait - mais les concepteurs de Java estimaient 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. Les interfaces multiples sont beaucoup moins susceptibles de provoquer des conflits difficiles à résoudre que plusieurs classes parentes.
Parce que l'héritage est utilisé de manière excessive même quand vous ne pouvez pas dites "hé, cette méthode semble utile, je vais également étendre cette classe".
public class MyGodClass extends AppDomainObject, HttpServlet, MouseAdapter,
AbstractTableModel, AbstractListModel, AbstractList, AbstractMap, ...
La réponse de cette question réside dans le fonctionnement interne du compilateur Java (chaînage des constructeurs). ) fonctionnement interne du compilateur Java:
public class Bank {
public void printBankBalance(){
System.out.println("10k");
}
}
class SBI extends Bank{
public void printBankBalance(){
System.out.println("20k");
}
}
Après avoir compilé cela ressemble à ceci:
public class Bank {
public Bank(){
super();
}
public void printBankBalance(){
System.out.println("10k");
}
}
class SBI extends Bank {
SBI(){
super();
}
public void printBankBalance(){
System.out.println("20k");
}
}
lorsque nous étendons la classe et en créons un objet, une chaîne de constructeurs s'exécutera jusqu'à la classe Object
.
Le code ci-dessus fonctionnera bien. mais si nous avons une autre classe appelée Car
qui étend Bank
et une hybride (classe à héritages multiples) appelée SBICar
:
class Car extends Bank {
Car() {
super();
}
public void run(){
System.out.println("99Km/h");
}
}
class SBICar extends Bank, Car {
SBICar() {
super(); //NOTE: compile time ambiguity.
}
public void run() {
System.out.println("99Km/h");
}
public void printBankBalance(){
System.out.println("20k");
}
}
Dans ce cas, SBICar ne parviendra pas à créer une chaîne de constructeur ( ambiguïté du temps de compilation ).
Pour les interfaces, cela est autorisé car nous ne pouvons pas en créer d’objet.
Pour le nouveau concept de default
et static
, veuillez vous référer à la méthode valeur par défaut dans l'interface .
J'espère que cela résoudra votre question. Merci.
L'implémentation de plusieurs interfaces est très utile et ne cause pas beaucoup de problèmes aux développeurs de langage ni aux programmeurs. Donc c'est permis. L'héritage multiple, bien qu'utile également, peut causer de graves problèmes aux utilisateurs (redouté diamant de la mort ). Et la plupart des choses que vous faites avec l'héritage multiple peuvent aussi se faire par composition ou en utilisant des classes internes. Donc, l'héritage multiple est interdit car il apporte plus de problèmes que de gains.
Java prend en charge plusieurs héritages via des interfaces uniquement. Une classe peut implémenter un nombre illimité d'interfaces, mais ne peut étendre qu'une classe.
L'héritage multiple n'est pas pris en charge car il conduit à un problème de diamant mortel. Cependant, cela peut être résolu, mais cela conduit à un système complexe, de sorte que l'héritage multiple a été abandonné par les Java).
Dans un livre blanc intitulé "Java: an Overview", rédigé par James Gosling en février 1995 ( lien ), on peut comprendre pourquoi l'héritage multiple n'est pas pris en charge en Java.
Selon Gosling:
"Java en omet de nombreuses fonctionnalités peu utilisées, mal comprises et déroutantes du C++ qui, selon notre expérience, apportent plus de problèmes que d'avantages. Il s'agit principalement d'une surcharge d'opérateurs (bien qu'elle comporte une surcharge de méthodes), d'un héritage multiple et de coercitions automatiques étendues."
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 de C++ avec l'héritage multiple est que cela conduit à plus de problèmes qu'il n'en valait la peine.
Une interface est un contrat d'éléments que votre classe doit mettre en œuvre. 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 cas d'héritage multiple, cela peut devenir extrêmement déroutant).
Autoriser plusieurs interfaces vous permet d'utiliser des modèles de conception (tels que Adapter) pour résoudre les mêmes types de problèmes que vous pouvez résoudre en utilisant plusieurs héritages, mais de manière beaucoup plus fiable et prévisible.
Vous pouvez trouver une réponse précise à cette requête dans la page de documentation Oracle à propos de héritage multiple
Héritage multiple d'état: Possibilité d'hériter de champs de plusieurs classes
Une des raisons pour lesquelles le langage de programmation Java ne vous permet pas d'étendre plus d'une classe est d'éviter les problèmes d'héritage multiple d'état, qui est la possibilité d'hériter des champs de plusieurs classes
Si l'héritage multiple est autorisé et que vous créez un objet en instanciant cette classe, cet objet héritera des champs de toutes les superclasses de la classe. Cela causera deux problèmes.
Héritage multiple de l'implémentation: Possibilité d'hériter des définitions de méthodes de plusieurs classes
Problèmes avec cette approche: name conflic ts et ambiguity. Si une sous-classe et une super-classe contiennent le même nom de méthode (et la même signature), le compilateur ne peut pas déterminer la version à invoquer.
Mais Java prend en charge ce type d'héritage multiple avec méthodes par défaut , qui ont été introduites depuis la Java 8. Le Java fournit certaines règles pour déterminer la méthode par défaut utilisée par une classe particulière.
Reportez-vous au message 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: Possibilité pour une classe d'implémenter plus d'une interface.
Etant donné que l'interface ne contient pas de champs mutables, vous n'avez pas à vous soucier des problèmes résultant de l'héritage multiple d'état.
On dit que l'état des objets est référé 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
Comme ce sujet n’est pas proche, je posterai cette réponse, j’espère que cela aidera quelqu'un à comprendre pourquoi Java ne permet pas l’héritage multiple.
Considérez la classe suivante:
public class Abc{
public void doSomething(){
}
}
Dans ce cas la classe Abc ne prolonge rien non? Pas si vite, cette classe implicite étend la classe Object, classe de base qui permet que tout fonctionne en Java. Tout est un objet.
Si vous essayez d'utiliser la classe ci-dessus, vous verrez que votre IDE vous permet d'utiliser des méthodes telles que: equals(Object o)
, toString()
, etc., mais vous n'avez pas déclaré ces méthodes, elles venaient de la classe de base Object
Tu pourrais essayer:
public class Abc extends String{
public void doSomething(){
}
}
C'est bien, parce que votre classe n'implicite pas Object
mais étend String
parce que vous l'avez dit. Considérez le changement suivant:
public class Abc{
public void doSomething(){
}
@Override
public String toString(){
return "hello";
}
}
Maintenant, votre classe retournera toujours "bonjour" si vous appelez toString ().
Maintenant, imaginez le cours suivant:
public class Flyer{
public void makeFly(){
}
}
public class Bird extends Abc, Flyer{
public void doAnotherThing(){
}
}
Encore une fois, la classe Flyer
implique implicitement Object qui a la méthode toString()
, toute classe aura cette méthode car elle étend tous Object
indirectement, donc, si vous appelez toString()
de Bird
, quelle toString()
Java devrait utiliser? De Abc
ou Flyer
? Cela se produira avec toutes les classes qui essaient d’étendre deux classes ou plus, pour éviter ce genre de "collision de méthodes", elles ont construit l’idée de interface, vous pouvez les penser en tant que classe abstraite cela n'allonge pas Object indirectement. Puisqu'ils sont abstraits, ils devront être implémentés par une classe, qui est un objet (vous ne pouvez pas instancier une interface seule, ils doivent être mis en œuvre par une classe), donc tout continuera à bien fonctionner.
Pour différencier les classes des interfaces, le mot clé implémente était réservé aux interfaces.
Vous pouvez implémenter n'importe quelle interface de votre choix dans la même classe, car ils n'allongent rien par défaut (mais vous pouvez créer une interface qui étend une autre interface, mais là encore, l'interface "père" n'allonge pas Object "), donc une interface est juste une interface et ils ne souffriront pas de "méthodes signature colissions", s'ils le font, le compilateur vous avertira et vous devrez simplement changer la méthode signature pour la corriger (signature = méthode nom + paramètres + type de retour).
public interface Flyer{
public void makeFly(); // <- method without implementation
}
public class Bird extends Abc implements Flyer{
public void doAnotherThing(){
}
@Override
public void makeFly(){ // <- implementation of Flyer interface
}
// Flyer does not have toString() method or any method from class Object,
// no method signature collision will happen here
}
Par exemple, deux classes A, B ayant la même méthode m1 (). Et la classe C s'étend à la fois A, B.
class C extends A, B // for explaining purpose.
Maintenant, la classe C cherchera la définition de m1. Tout d’abord, il cherchera en classe s’il ne l’a pas trouvé, puis vérifiera auprès des parents. Les deux A, B ayant la définition Donc, voici quelle ambiguïté se produit quelle définition devrait choisir. So Java NE PREND PAS EN CHARGE UN HÉRITAGE MULTIPLE.
Java ne prend pas en charge l'héritage multiple pour deux raisons:
Object
. Quand elle hérite de plus d'une super classe, la sous-classe obtient l'ambiguïté d'acquérir la propriété de la classe Object.super()
pour appeler le constructeur de la classe supper. Si la classe a plus d'une super classe, il est confus.Ainsi, lorsqu'une classe s'étend de plus d'une super classe, nous obtenons une erreur de compilation.
Prenons 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, l'appel de la méthode de la classe Test1 ou de la classe Test2 sera ambigu, mais il n'y a pas d'ambiguïté de ce type pour l'interface car aucune implémentation n'existe dans l'interface.
Parce qu'une interface n'est qu'un contrat. Et une classe est en fait un conteneur pour les données.
Java ne prend pas en charge l'héritage multiple, l'héritage par trajets multiples et hybride en raison d'un problème d'ambiguïté:
Scenario for multiple inheritance: Let us take class A , class B , class C. class A has alphabet(); method , class B has also alphabet(); method. Now class C extends A, B and we are creating object to the subclass i.e., class C , so C ob = new C(); Then if you want call those methods ob.alphabet(); which class method takes ? is class A method or class B method ? So in the JVM level ambiguity problem occurred. Thus Java does not support multiple inheritance.
Lien de référence:https://plus.google.com/u/0/communities/ 102217496457095083679
Prenons par exemple le cas où la classe A utilise une méthode getSomething et la classe B, une méthode getSomething, et les classes C, A et B. Que se passerait-il si quelqu'un appelé C.getSomething? Il n'y a aucun moyen de déterminer quelle méthode appeler.
Les interfaces spécifient essentiellement les méthodes qu'une classe d'implémentation doit contenir. Une classe qui implémente plusieurs interfaces signifie simplement que cette classe doit implémenter les méthodes de toutes ces interfaces. Ce qui ne poserait aucun problème décrit ci-dessus.