为什么Java中没有多重继承,但允许实现多个接口?
Java 不允许多重继承,但它允许实现多个接口。为什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
Java 不允许多重继承,但它允许实现多个接口。为什么?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(21)
因为接口只指定类正在做什么,而不是它如何做。
多重继承的问题在于,两个类可能定义做同一件事的不同方式,而子类无法选择选择哪一种。
Because interfaces specify only what the class is doing, not how it is doing it.
The problem with multiple inheritance is that two classes may define different ways of doing the same thing, and the subclass can't choose which one to pick.
我的一位大学导师是这样向我解释的:
因此,主要问题之一是,如果您有两个父类,它们可能对同一功能有不同的实现,或者可能有两个具有相同名称的不同功能,如我的讲师的示例所示。然后你必须决定你的子类将使用哪一个。当然,有很多方法可以处理这个问题——C++就是这么做的——但Java的设计者认为这会让事情变得太复杂。
但是,通过接口,您可以描述类能够执行的操作,而不是借用另一个类的方法来执行操作。与多个父类相比,多个接口不太可能导致需要解决的棘手冲突。
One of my college instructors explained it to me this way:
So one of the main issues is that if you have two parent classes, they might have different implementations of the same feature — or possibly two different features with the same name, as in my instructor's example. Then you have to deal with deciding which one your subclass is going to use. There are ways of handling this, certainly — C++ does so — but the designers of Java felt that this would make things too complicated.
With an interface, though, you're describing something the class is capable of doing, rather than borrowing another class's method of doing something. Multiple interfaces are much less likely to cause tricky conflicts that need to be resolved than are multiple parent classes.
因为继承被过度使用,即使您不能说“嘿,那个方法看起来很有用,我也会扩展那个类”。
Because inheritance is overused even when you can't say "hey, that method looks useful, I'll extend that class as well".
这个问题的答案在于java编译器的内部工作原理(构造函数链)。
如果我们看到java编译器的内部工作原理:
编译后如下所示:
当我们扩展类并创建它的对象时,一个构造函数链将运行到
Object
类。上面的代码可以正常运行。但如果我们有另一个名为
Car
的类,它扩展了Bank
和一个名为SBICar
的混合(多重继承)类:在这种情况下(SBICar)将无法创建构造函数链(编译时歧义)。
对于接口,这是允许的,因为我们无法创建它的对象。
有关
default
和static
方法的新概念,请参阅 界面默认。希望这能解决您的疑问。
谢谢。
The answer of this question is lies in the internal working of java compiler(constructor chaining).
If we see the internal working of java compiler:
After compiling this look like:
when we extends class and create an object of it, one constructor chain will run till
Object
class.Above code will run fine. but if we have another class called
Car
which extendsBank
and one hybrid(multiple inheritance) class calledSBICar
:In this case(SBICar) will fail to create constructor chain(compile time ambiguity).
For interfaces this is allowed because we cannot create an object of it.
For new concept of
default
andstatic
method kindly refer default in interface.Hope this will solve your query.
Thanks.
您可以在有关多重继承<的oracle文档页面中找到此查询的准确答案< /a>
在这种情况下,当您创建一个对象时:它将继承所有超类的字段。这会导致两个问题。
这种方法会导致名称冲突和歧义。如果子类和超类包含相同的方法名称(和签名),编译器无法确定要调用哪个版本。
Java 通过 默认方法 支持这种类型的多重继承,因为Java 8 发布。 Java 编译器提供了一些规则来确定特定类使用哪种默认方法。
有关解决钻石问题的更多详细信息,请参阅下面的 SE 帖子:
Java 8 中抽象类和接口有什么区别?
由于接口不包含可变字段,因此您不必担心这里由于状态的多重继承而导致的问题。
You can find accurate answer for this query in oracle documentation page about multiple inheritance
In this case, When you create an object : It will inherit fields from all of the superclasses. It will cause two issues.
This approach causes name conflicts and ambiguity. If a subclass and superclass contain same method name (and signature), compiler can't determine which version to invoke.
Java supports this type of multiple inheritance with default methods, since Java 8 release. The Java compiler provides some rules to determine which default method a particular class uses.
Refer to below SE post for more details on resolving diamond problem:
What are the differences between abstract classes and interfaces in Java 8?
Since interface does not contain mutable fields, you need not worry about problems that result from multiple inheritance of state here.
Java 不支持多重继承有两个原因:
Object
类的子类。当它继承自多个超类时,子类就会产生歧义获取Object类的属性。
super()
来调用超级类构造函数。如果该类有多个超类,则
感到困惑。
因此,当一个类从多个超类扩展时,我们会收到编译时错误。
Java does not support multiple inheritance because of two reasons:
Object
class. When it inherits from more than one super class, sub class gets the ambiguity toacquire the property of Object class..
super()
to invoke thesupper class constructor. If the class has more than one super class, it
gets confused.
So when one class extends from more than one super class, we get compile time error.
Java 仅通过接口支持多重继承。一个类可以实现任意数量的接口,但只能扩展一个类。
不支持多重继承,因为它会导致致命的钻石问题。然而,它可以解决,但会导致系统复杂,因此多重继承已被 Java 创始人放弃。
James Gosling 在 1995 年 2 月发表的题为“Java:概述”的白皮书中(链接 - 第 2 页)给出了为什么 Java 不支持多重继承的想法。
根据高斯林的说法:
Java supports multiple inheritance through interfaces only. A class can implement any number of interfaces but can extend only one class.
Multiple inheritance is not supported because it leads to deadly diamond problem. However, it can be solved but it leads to complex system so multiple inheritance has been dropped by Java founders.
In a white paper titled “Java: an Overview” by James Gosling in February 1995(link - page 2) gives an idea on why multiple inheritance is not supported in Java.
According to Gosling:
实现多个接口非常有用,并且不会给语言实现者或程序员带来太多问题。所以这是允许的。多重继承虽然也很有用,但可能会给用户带来严重的问题(可怕的死亡钻石)。使用多重继承所做的大多数事情也可以通过组合或使用内部类来完成。因此多重继承是被禁止的,因为带来的问题多于收益。
Implementing multiple interfaces is very useful and doesn't cause much problems to language implementers nor programmers. So it is allowed. Multiple inheritance while also useful, can cause serious problems to users (dreaded diamond of death). And most things you do with multiple inheritance can be also done by composition or using inner classes. So multiple inheritance is forbidden as bringing more problems than gains.
据说对象状态是根据其中的字段来引用的,如果继承了太多的类,它就会变得不明确。这是链接
http://docs.oracle.com/javase/tutorial /java/IandI/multipleinheritance.html
It is said that objects state is referred with respect to the fields in it and it would become ambiguous if too many classes were inherited. Here is the link
http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
由于这个主题还没有结束,我将发布这个答案,我希望这可以帮助人们理解为什么java不允许多重继承。
考虑下面的类:
在这种情况下,类 Abc 没有扩展任何东西,对吗?没那么快,这个类隐式扩展了 Object 类,它是允许一切在 java 中工作的基类。一切都是对象。
如果您尝试使用上面的类,您会发现您的 IDE 允许您使用以下方法:
equals(Object o)
、toString()
等,但是您没有声明这些方法,它们来自基类Object
你可以尝试:
这很好,因为你的类不会隐式扩展
Object
而是会扩展String
因为你说过。考虑以下更改:现在,如果您调用 toString(),您的类将始终返回“hello”。
现在想象一下下面的类:
同样,类
Flyer
隐式扩展了具有方法toString()
的 Object,任何类都将具有此方法,因为它们都扩展了Object 间接地,所以,如果您从
Bird
调用toString()
,java 必须使用哪个toString()
?来自Abc
还是Flyer
?任何试图扩展两个或多个类的类都会发生这种情况,为了避免这种“方法冲突”,他们构建了接口的思想,基本上你可以将它们视为抽象类它不会间接扩展 Object。由于它们是抽象,因此它们必须由一个类实现,该类是一个对象(您不能单独实例化接口,它们必须由类实现),因此一切都会继续正常进行。为了区分类和接口,关键字 implements 仅为接口保留。
您可以在同一个类中实现您喜欢的任何接口,因为它们默认情况下不会扩展任何内容(但您可以创建一个扩展另一个接口的接口,但同样,“父亲”接口不会扩展“Object”),因此接口是只是一个接口,它们不会遭受“方法签名冲突”的影响,如果这样做,编译器会向您发出警告,您只需更改方法签名即可修复它(签名=方法名称+参数+返回类型)。
Since this topic is not close I'll post this answer, I hope this helps someone to understand why java does not allow multiple inheritance.
Consider the following class:
In this case the class Abc does not extends nothing right? Not so fast, this class implicit extends the class Object, base class that allow everything work in java. Everything is an object.
If you try to use the class above you'll see that your IDE allow you to use methods like:
equals(Object o)
,toString()
, etc, but you didn't declare those methods, they came from the base classObject
You could try:
This is fine, because your class will not implicit extends
Object
but will extendsString
because you said it. Consider the following change:Now your class will always return "hello" if you call toString().
Now imagine the following class:
Again class
Flyer
implicit extends Object which has the methodtoString()
, any class will have this method since they all extendsObject
indirectly, so, if you calltoString()
fromBird
, whichtoString()
java would have to use? FromAbc
orFlyer
? This will happen with any class that try to extends two or more classes, to avoid this kind of "method collision" they built the idea of interface, basically you could think them as an abstract class that does not extends Object indirectly. Since they are abstract they will have to be implemented by a class, which is an object (you cannot instanciate an interface alone, they must be implemented by a class), so everything will continue to work fine.To differ classes from interfaces, the keyword implements was reserved just for interfaces.
You could implement any interface you like in the same class since they does not extends anything by default (but you could create a interface that extends another interface, but again, the "father" interface would not extends Object"), so an interface is just an interface and they will not suffer from "methods signature colissions", if they do the compiler will throw a warning to you and you will just have to change the method signature to fix it (signature = method name + params + return type).
出于同样的原因,C# 不允许多重继承,但允许您实现多个接口。
从具有多重继承的 C++ 中吸取的教训是,它会导致比其价值更多的问题。
接口是您的类必须实现的事物的契约。您无法从该界面获得任何功能。继承允许您继承父类的功能(在多重继承中,这可能会变得非常混乱)。
允许多个接口允许您使用设计模式(如适配器)来解决使用多重继承可以解决的相同类型的问题,但以更可靠和可预测的方式。
For the same reason C# doesn't allow multiple inheritence but allows you to implement multiple interfaces.
The lesson learned from C++ w/ multiple inheritence was that it lead to more issues than it was worth.
An interface is a contract of things your class has to implement. You don't gain any functionality from the interface. Inheritence allows you to inherit the functionality of a parent class (and in multiple-inheritence, that can get extremely confusing).
Allowing multiple interfaces allows you to use Design Patterns (like Adapter) to solve the same types of issues you can solve using multiple inheritence, but in a much more reliable and predictable manner.
例如两个类 A、B 具有相同的方法 m1()。并且类 C 扩展了 A、B。
现在,类 C 将搜索 m1 的定义。首先,它会在班级中查找,如果没有找到,则会向家长班级查找。 A、B 都有定义 所以这里出现了应该选择哪个定义的歧义。
所以JAVA不支持多重继承。
For example two class A,B having same method m1(). And class C extends both A, B.
Now, class C will search the definition of m1. First, it will search in class if it didn't find then it will check to parents class. Both A, B having the definition So here ambiguity occur which definition should choose.
So JAVA DOESN'T SUPPORT MULTIPLE INHERITANCE.
我们都知道,以简单的方式,我们可以继承(扩展)一个类,但我们可以实现如此多的接口..那是因为在接口中我们不给出实现,只是说功能。假设如果java可以扩展这么多类并且这些类具有相同的方法..在这一点上,如果我们尝试在子类中调用超类方法,那么应该运行什么方法??,编译器会感到困惑
示例:- 尝试多个扩展
但在接口中,这些方法没有主体,我们应该在子类中实现它们。
尝试多种实现
所以不用担心..
in simple manner we all know, we can inherit(extends) one class but we can implements so many interfaces.. that is because in interfaces we don't give an implementation just say the functionality. suppose if java can extends so many classes and those have same methods.. in this point if we try to invoke super class method in the sub class what method suppose to run??, compiler get confused
example:- try to multiple extends
but in interfaces those methods don't have bodies we should implement those in sub class..
try to multiple implements
so no worries..
由于不明确,类不支持多重继承。
(这一点在上面使用 super 关键字的答案中已经清楚地解释了)
现在对于接口,
直到 Java 7,接口都无法定义方法的实现。因此,如果类从具有相同方法签名的多个接口实现,则该方法的实现将由该类提供。
从 java 8 开始,接口也可以有方法的实现。因此,如果类实现了两个或多个具有相同方法签名和实现的接口,那么也必须在该类中实现该方法。
从 Java 9 开始,接口可以包含静态方法、私有方法、私有静态方法。
接口功能的修改(基于 java 版本 7,8,9)
Multiple inheritance is not supported by class because of ambiguity.
(this point is explained clearly in above answers using super keyword)
Now for interfaces,
upto Java 7, interfaces could not define the implementation of methods. So if class implements from multiple interfaces having same method signature then implementation of that method is to be provided by that class.
from java 8 onwards, interfaces can also have implementation of methods. So if class implements two or more interfaces having same method signature with implementation, then it is mandated to implement the method in that class also.
From Java 9 onwards, interfaces can contain Static methods, Private methods, Private Static methods.
Modifications in features of Interfaces (over java version-7,8,9)
因为接口只是一个契约。而类实际上是数据的容器。
Because an interface is just a contract. And a class is actually a container for data.
考虑一个场景,其中 Test1、Test2 和 Test3 是三个类。 Test3 类继承 Test2 和 Test1 类。如果 Test1 和 Test2 类具有相同的方法,并且您从子类对象调用它,则调用 Test1 或 Test2 类的方法会存在歧义,但接口不存在这种歧义,因为接口中没有实现。
Consider a scenario where Test1, Test2 and Test3 are three classes. The Test3 class inherits Test2 and Test1 classes. If Test1 and Test2 classes have same method and you call it from child class object, there will be ambiguity to call method of Test1 or Test2 class but there is no such ambiguity for interface as in interface no implementation is there.
Java 不支持多重继承、多路径和混合继承,因为存在以下歧义
问题。
多重继承的场景:让我们以类A、类B、类C为例。类A有alphabet();方法,B类也有alphabet();方法。现在类 C 扩展了 A、B,我们正在为子类创建对象,即类 C ,因此 C ob = new C();然后如果你想调用这些方法 ob.alphabet();哪个类方法采用?是A类方法还是B类方法?所以在JVM层面就出现了歧义问题。因此Java不支持多重继承。
多重继承
Java does not support multiple inheritance , multipath and hybrid inheritance because of the following ambiguity
problem.
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.
multiple inheritance
举个例子,类 A 有一个 getSomething 方法,类 B 有一个 getSomething 方法,类 C 扩展 A 和 B。如果有人调用 C.getSomething 会发生什么?无法确定调用哪个方法。
接口基本上只是指定实现类需要包含哪些方法。实现多个接口的类仅意味着该类必须实现所有这些接口的方法。 Whci 不会导致上述任何问题。
Take for example the case where Class A has a getSomething method and class B has a getSomething method and class C extends A and B. What would happen if someone called C.getSomething? There is no way to determine which method to call.
Interfaces basically just specify what methods a implementing class needs to contain. A class that implements multiple interfaces just means that class has to implement the methods from all those interfaces. Whci would not lead to any issues as described above.
该图解释了多重继承的问题。
派生类的继承成员是什么?它在派生类中仍然是私有的还是公开的?
为了在 Java 中避免出现此类问题,他们删除了多重继承。该图是面向对象编程问题的简单示例。
the image explaining the problem with multiple inheritances.
What is the inherited member of the derived class? it is still private or publically available in the derived class?
For not getting this type of problem in Java they removed multiple inheritance. This image is a simple example of an object-oriented programming problem.
* 这是一个简单的答案,因为我是 Java 初学者 *
考虑有三个类
X
、Y
和Z< /代码>。
所以我们像
X extends Y, Z
一样继承Y
和Z
都有一个具有相同返回类型和参数的方法alphabet()
。Y
中的方法alphabet()
表示显示第一个字母,而Z
中的方法 Alphabet 表示显示最后一个字母表。因此,当
X
调用alphabet()
时,就会出现歧义。是否显示显示第一个或最后字母???所以java不支持多重继承。
对于接口,请将
Y
和Z
视为接口。因此两者都将包含方法alphabet()
的声明,但不包含定义。它不会告诉是否显示第一个字母表或最后一个字母表或其他任何内容,而只是声明一个方法alphabet()
。因此没有理由提出歧义。我们可以在类X
中使用我们想要的任何内容来定义该方法。总之,接口定义是在实现之后完成的,因此不会造成混淆。
* This is a simple answer since I'm a beginner in Java *
Consider there are three classes
X
,Y
andZ
.So we are inheriting like
X extends Y, Z
And both
Y
andZ
is having a methodalphabet()
with same return type and arguments. This methodalphabet()
inY
says to display first alphabet and method alphabet inZ
says display last alphabet.So here comes ambiguity when
alphabet()
is called byX
. Whether it says to display first or last alphabet???So java is not supporting multiple inheritance.
In case of Interfaces, consider
Y
andZ
as interfaces. So both will contain the declaration of methodalphabet()
but not the definition. It won't tell whether to display first alphabet or last alphabet or anything but just will declare a methodalphabet()
. So there is no reason to raise the ambiguity. We can define the method with anything we want inside classX
.So in a word, in Interfaces definition is done after implementation so no confusion.
这是保持低复杂性的决定。
使用混合继承,实现起来会更加复杂,而且无论如何,多重继承也可以通过其他方式实现。
It is a decision to keep the complexity low.
With hybrid inheritance, things would have been more complicated to implement, and anyways what is achievable by multiple inheritances is also with other ways.