为什么Java不允许多重继承,但允许使用默认实现兼容多个接口
我不是在问这个->Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
在Java中,不允许多重继承,但是在Java 8之后,接口可以有默认方法(可以实现方法本身),就像抽象类一样。在这种情况下,还应该允许多重继承
interface TestInterface
{
// abstract method
public void square(int a);
// default method
default void show()
{
System.out.println("Default Method Executed");
}
}
# 1 楼答案
语言设计者已经考虑过了,所以这些都是由编译器来实现的。所以如果你定义:
为两个接口实现一个类:
你会得到一个编译错误;你需要重写
go
以避免在它周围产生歧义但你可能会想,你可以在这里欺骗编译器,方法是:
你可能认为
First::go
已经为Second::go
提供了一个实现,应该没问题。这一点考虑得太多,因此也无法编译我要强调的最后一点是,即使在java中添加了新的元素,也不允许多重继承,即不继承来自接口的静态方法。默认情况下继承静态方法:
但是,如果我们对一个接口进行更改(并且可以实现多个接口,而不是类):
现在,编译器和
JLS
也禁止这样做:# 2 楼答案
接口中的
default
方法带来了一个问题:实现类应该明确定义使用哪个默认方法,或者定义自己的方法
因此,Java-8中的
default
方法不利于多重继承。默认方法背后的主要动机是,如果在某个时刻我们需要向现有接口添加一个方法,我们可以在不更改现有实现类的情况下添加一个方法。这样,该界面仍然与旧版本兼容。然而,我们应该记住使用默认方法的动机,并且应该保持接口和实现的分离# 3 楼答案
事情并不是那么简单
如果一个类实现了多个定义具有相同签名的默认方法的接口,编译器将强制您为该类重写该方法
例如,这两个接口:
它不会编译:
您应该定义/覆盖该方法以消除歧义
例如,您可以委托给
Bar
实现,例如:或者委托给
Foo
实现,例如:或者仍然定义另一种行为:
该约束表明,即使对于接口默认方法,Java也不允许多重继承
我认为我们不能对多重继承应用相同的逻辑,因为可能会出现多重问题,主要有:
A
和B
类中定义的int foo
字段,您想要子类化,但它们的含义和意图并不相同李># 4 楼答案
多重继承的主要问题是排序(用于重写和调用super)、字段和构造函数;接口没有字段或构造函数,因此不会导致问题
如果你看一下其他语言,它们通常分为两大类:
具有多重继承的语言加上一些消除特殊情况歧义的功能:虚拟继承[C++],直接调用最派生类[C++]中的所有超构造函数,超类线性化[Python],用于超级[Python]的复杂规则,等等。
具有不同概念的语言,通常被称为接口,特征,混合,模块,等等。这些语言施加了一些限制,例如:没有构造函数[Java]或没有带参数的构造函数[Scala],没有可变字段[Java],重写的特定规则(例如,mixin优先于基类[Ruby],因此在需要一系列实用方法时可以包含它们),等等。Java已经成为这样一种语言
为什么仅仅通过禁止字段和构造函数就可以解决与多重继承相关的许多问题