为什么Java中没有多重继承,但允许实现多个接口?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2515477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
提问by abson
Java doesn't allow multiple inheritance, but it allows implementing multiple interfaces. Why?
Java 不允许多重继承,但它允许实现多个接口。为什么?
采纳答案by Bozho
Because interfaces specify only whatthe class is doing, not howit is doing it.
因为接口只指定什么类是做,而不是如何它是做什么的。
The problem with multiple inheritance is that two classes may define different waysof doing the same thing, and the subclass can't choose which one to pick.
多重继承的问题在于两个类可能定义了不同的做同一件事的方式,而子类无法选择选择哪一个。
回答by Snake
Because an interface is just a contract. And a class is actually a container for data.
因为接口只是一个契约。而类实际上是数据的容器。
回答by Justin Niessner
For the same reason C# doesn't allow multiple inheritence but allows you to implement multiple interfaces.
出于同样的原因,C# 不允许多重继承,但允许您实现多个接口。
The lesson learned from C++ w/ multiple inheritence was that it lead to more issues than it was worth.
从具有多重继承的 C++ 中吸取的教训是,它导致的问题多于其价值。
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.
允许多个接口允许您使用设计模式(如适配器)来解决您可以使用多重继承解决的相同类型的问题,但以更可靠和可预测的方式。
回答by Michael Borgwardt
Because inheritance is overused even when you can'tsay "hey, that method looks useful, I'll extend that class as well".
因为即使你不能说“嘿,那个方法看起来很有用,我也会扩展那个类”,因为继承被过度使用了。
public class MyGodClass extends AppDomainObject, HttpServlet, MouseAdapter,
AbstractTableModel, AbstractListModel, AbstractList, AbstractMap, ...
回答by Tadeusz Kopec
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.
实现多个接口非常有用,并且不会给语言实现者或程序员带来太多问题。所以是允许的。多重继承虽然也很有用,但会给用户带来严重的问题(可怕的死亡钻石)。您使用多重继承所做的大多数事情也可以通过组合或使用内部类来完成。因此禁止多重继承,因为它带来的问题多于收益。
回答by Syntactic
One of my college instructors explained it to me this way:
我的一位大学老师是这样向我解释的:
Suppose I have one class, which is a Toaster, and another class, which is NuclearBomb. They both might have a "darkness" setting. They both have an on() method. (One has an off(), the other doesn't.) If I want to create a class that's a subclass of both of these...as you can see, this is a problem that could really blow up in my face here.
假设我有一个类,它是烤面包机,另一个类是核弹。他们都可能有一个“黑暗”设置。他们都有一个 on() 方法。(一个有一个 off(),另一个没有。)如果我想创建一个类,它是这两个的子类......正如你所看到的,这是一个可能真的在我面前爆炸的问题.
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.
因此,主要问题之一是,如果您有两个父类,它们可能具有相同功能的不同实现——或者可能有两个具有相同名称的不同功能,如我教师的示例。然后你必须决定你的子类将使用哪一个。当然,有一些方法可以处理这个问题——C++ 就是这样做的——但是 Java 的设计者认为这会使事情变得过于复杂。
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.
但是,使用接口,您是在描述类能够做的事情,而不是借用另一个类的方法来做某事。与多个父类相比,多个接口不太可能导致需要解决的棘手冲突。
回答by John Kane
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.
以类 A 有一个 getSomething 方法而类 B 有一个 getSomething 方法而类 C 扩展 A 和 B 的情况为例。如果有人调用 C.getSomething 会发生什么?无法确定调用哪个方法。
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.
接口基本上只是指定实现类需要包含哪些方法。实现多个接口的类仅意味着该类必须实现所有这些接口的方法。Whci 不会导致上述任何问题。
回答by Karthik GVD
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
http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
回答by Nikhil Kumar
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.
考虑一个场景,其中 Test1、Test2 和 Test3 是三个类。Test3 类继承了 Test2 和 Test1 类。如果 Test1 和 Test2 类具有相同的方法并且您从子类对象调用它,则调用 Test1 或 Test2 类的方法会有歧义,但接口没有这种歧义,因为在接口中没有实现。
回答by Murillo Ferreira
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.
由于这个话题不是很接近我会发布这个答案,我希望这有助于有人理解为什么 java 不允许多重继承。
Consider the following class:
考虑以下类:
public class Abc{
public void doSomething(){
}
}
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.
在这种情况下,类 Abc 不会扩展任何东西,对吗?没那么快,这个类隐式扩展了类Object,基类允许一切在java中工作。一切都是对象。
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 class Object
如果您尝试使用类上面,你会看到你的IDE允许您使用类似的方法:equals(Object o)
,toString()
,等等,但你没有申报这些方法,他们就从基类Object
You could try:
你可以试试:
public class Abc extends String{
public void doSomething(){
}
}
This is fine, because your class will not implicit extends Object
but will extends String
because you said it. Consider the following change:
这很好,因为您的类不会隐式扩展,Object
而是会String
因为您说过而扩展。考虑以下更改:
public class Abc{
public void doSomething(){
}
@Override
public String toString(){
return "hello";
}
}
Now your class will always return "hello" if you call toString().
现在,如果您调用 toString(),您的类将始终返回“hello”。
Now imagine the following class:
现在想象一下下面的类:
public class Flyer{
public void makeFly(){
}
}
public class Bird extends Abc, Flyer{
public void doAnotherThing(){
}
}
Again class Flyer
implicit extends Object which has the method toString()
, any class will have this method since they all extends Object
indirectly, so, if you call toString()
from Bird
, which toString()
java would have to use? From Abc
or Flyer
? 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 abstractthey 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.
同样Flyer
,具有方法的类隐式扩展对象toString()
,任何类都将具有此方法,因为它们都是Object
间接扩展的,因此,如果您调用toString()
from Bird
,则toString()
必须使用哪个java?从Abc
或Flyer
? 任何试图扩展两个或多个类的类都会发生这种情况,为了避免这种“方法冲突”,他们构建了interface的想法,基本上你可以将它们视为不间接扩展 Object的抽象类。由于它们是抽象的,因此必须由一个类来实现,该类是一个对象(你不能单独实例化一个接口,它们必须由一个类实现),所以一切都会继续正常工作。
To differ classes from interfaces, the keyword implementswas reserved just for interfaces.
为了将类与接口区分开来,关键字implements仅用于接口。
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).
你可以在同一个类中实现你喜欢的任何接口,因为它们默认不扩展任何东西(但你可以创建一个扩展另一个接口的接口,但同样,“父”接口不会扩展对象),所以一个接口是只是一个接口,他们不会受到“方法签名冲突”的影响,如果他们这样做,编译器会向您发出警告,您只需要更改方法签名即可修复它(签名=方法名称+参数+返回类型) .
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
}