我的答案正确吗?
是的,大多数情况下,当然在您描述的上下文中。这不是多重继承:
就是你说的,多级单继承。
这是多重继承:从两个或多个彼此没有任何“是”关系的基础继承;这将继承自不相关的行,或者从先前分歧的行(在 Java 中,因为Object 始终是基数,所以它将是后者):
(图片来源:http://yuml.me 处于“邋遢”模式)
内部实际发生了什么?
正如您所说:有多个级别。当编译器解析实例上的成员时:
obj.member
...它查看obj 的类型(在这种情况下是一个类,比如ClassB)是否具有member,或者是因为它直接提供它,还是它通过继承获得它。在运行时,JVM 使用对象实际拥有的member。
我在上面说“大部分”的原因是 Java 具有接口,并且从 Java 8 开始,它在接口上具有“默认方法”。这使事情有点复杂化,但在你描述面试官对Object、ClassA 和ClassB 的描述的背景下,你对级别的回答是正确的。
在 Java 中,接口总是使某些东西与两种不同类型具有“是一种”关系成为可能:它继承自的类类型,以及它实现的几种接口类型中的任何一种.没有默认方法的接口实际上不是多重继承(类必须提供实现),但它们确实使一个类可以从不相关的类型树中拥有多个“is a”关系。 (我不是学者,学者可能会争辩说他们以学术方式提供多重继承。)
使用 Java 8,接口可以提供它们定义的方法的默认实现,即使在实际层面上,这也确实模糊了界限。让我们更深入地看一下:
假设我们有ClassA:
class ClassA {
void doSomething() {
// Code here
}
}
和Interface1:
interface Interface1 {
default void doSomethingElse() { // Requires Java 8
// Code here
}
}
最后是ClassB:
class ClassB extends ClassA implements Interface1 {
}
ClassB 从ClassA 继承doSomething 的实现。但它也从Interface1 获取doSomethingElse 的“默认”版本。我们没有在ClassB 中实现它,但ClassB 不是抽象的:它确实有doSomethingElse。它从接口获取。我在那里使用了“gets”而不是“inherits”这个词,但这看起来很像继承默认方法。
这基本上是多重继承的“light”(如“light beer”)。它解决了真正多重继承的棘手问题,例如:
-
super 的类型应该是什么? (Java 8 的回答:ClassA)
- 您以什么顺序运行构造函数? (Java 8 的回答:单沿袭构造函数链,接口没有构造函数。)
- 您是否运行多次继承的构造函数? (Java 8 的回答:你不能多次继承构造函数,接口没有它们。)
- 如果继承多个具有相同签名的方法会发生什么? (Java 8 的回答:如果其中一个来自基类,那就是使用的那个;基类的实现可以覆盖多个接口的默认方法。如果您在编译时有多个具有来自不同接口的相同签名的默认方法-时间,这是一个编译时错误。如果在未重新编译类的情况下更改了接口并且在运行时出现这种情况,则它是一个运行时
IncompatibleClassChangeError 异常,列出了冲突的默认方法。)