Java:如果A扩展B而B扩展了Object,那就是多重继承

Ank*_*rma 30 java oop inheritance class

我刚接受了一次采访,我被问到一个问题.

采访者 - Java是否支持多重继承?

- 不

Interviewer - Java中的每个类都扩展了类Object(除了Object类),如果我们在外部扩展一个类就像

Class A extends B{
  // some code here
}
Run Code Online (Sandbox Code Playgroud)

那么你可以说A类扩展了B类和Object类,这意味着它是多重继承.那你怎么说Java不支持多重继承呢?

- 实际上类B扩展了类Object,所以当你在类A中扩展类B时,类A间接地扩展了类Object.这是多级继承,而不是多重继承.

但我的回答并不能让他满意.

我的回答是否正确?或者我错在哪里?内部实际发生了什么?

T.J*_*der 39

我的回答是对的?

是的,主要是,当然在你描述的背景下.这不是多重继承:

对象^  -  ClassA ^  -  ClassB

这就是你所说的,具有多个级别的单一继承.

这是多重继承:从两个或多个没有任何"是"关系的基础继承; 这将是从不相关的行继承,或从以前分歧的行继承(在Java中,因为Object它总是一个基础,它将是后者):

Object ^  -  ClassA,Object ^  -  ClassB,ClassA ^  -  ClassC,ClassB ^  -  ClassC

(图片来源:http://yuml.me "scruffy"模式)

内部实际发生了什么?

正是你所说的:有多个层次.当编译器解析实例上的成员时:

obj.member
Run Code Online (Sandbox Code Playgroud)

...它看起来是否obj(在这种情况下是一个类,例如ClassB)的类型member,或者是因为它直接提供它还是通过继承它.在运行时,JVM使用member实际拥有的对象.


我上面"大部分"说的原因是Java有接口,而Java 8在接口上有"默认方法".这会使事情变得复杂了一点,但你对各级答案是你所描述的面试官说关于上下文正确Object,ClassAClassB.

在Java中,接口始终可以使某种东西与两种不同的类型具有"是一种"关系:它继承的类类型,以及它实现的几种接口类型.没有默认方法的接口不是实际的多重继承(类必须提供实现),但是它们确实使类可以从不相关的类型树中获得多个"是"关系.(我不是学者,有可能一个学者认为他们以学术方式提供多重继承.)

使用Java 8,接口可以提供它们定义的方法的默认实现,即使在实际级别上也能真正模糊这些行.让我们更深入地看一下:

说我们有ClassA:

class ClassA {
    void doSomething() {
        // Code here
    }
}
Run Code Online (Sandbox Code Playgroud)

并且Interface1:

interface Interface1 {
    default void doSomethingElse() { // Requires Java 8
        // Code here
    }
}
Run Code Online (Sandbox Code Playgroud)

最后ClassB:

class ClassB extends ClassA implements Interface1 {
}
Run Code Online (Sandbox Code Playgroud)

ClassB继承了doSomethingfrom 的实现ClassA.但它获得了doSomethingElse来自的"默认"版本Interface1.我们没有实现它ClassB,但ClassB不是抽象的:它确实有doSomethingElse.它从界面获取它.我用这个词"被",而不是"继承"在那里,但是这看起来很多像继承的默认方法.

这基本上是多重继承"轻"(如"淡啤酒").它完成了真正的多重继承的棘手问题,如:

  • 应该是什么类型的super?(Java的8的答案:ClassA)
  • 你在什么顺序运行构造函数?(Java 8的答案:单行构造函数链接,接口没有构造函数.)
  • 您是否多次运行多次继承的构造函数?(Java 8的答案:你不能多次继承构造函数,接口没有它们.)
  • 如果继承具有相同签名的多个方法会发生什么?(Java 8的答案:如果其中一个来自基类,那就是使用的那个;基类的实现可以覆盖多个接口的默认方法.如果你有多个默认方法在编译时使用来自不同接口的相同签名 - 时间,这是一个编译时错误.如果在没有重新编译类的情况下更改了接口并且在运行时出现了这种情况,那么它是一个运行时IncompatibleClassChangeError异常,列出了冲突的默认方法.)

  • 哇,多好的解释.但我只能做+1 :(有没有办法给+1000;) (3认同)
  • 那些照片很漂亮.我不知道为什么. (3认同)

MSR*_*MSR 7

你是对的

首先,Object类是每个类的超级/基类/父类,包括用户定义的类.

因此,即使我们没有明确提及它,用户定义的类默认扩展Object类.

就像是

class A 
class B extends A

 but compiler read it as 
class A extends Object
class B extends A
Run Code Online (Sandbox Code Playgroud)

证明

有关更多详细信息,请查看此java文档以获取继承


Nar*_*hai 5

我的回答是对的?

你说它是多级继承而不是多重继承是完全正确的.

只有层次结构的Object,所有类都不单独扩展Object.

面试官的反击:

如果所有类都扩展Object,那么Object将调用构造函数的次数A a = new A();

答案只有一次,那将是层次结构的根.