当前位置: 首页 > 面试题库 >

Java:如果A扩展了B和B扩展了对象,是多重继承吗

张亦
2023-03-14
问题内容

我刚刚有人问我一个问题。

问 -Java是否支持多重继承?

我 -不

问-Java中的每个类都扩展了类Object(类Object除外),如果我们从外部扩展了一个类,例如

Class A extends B{
  // some code here
}

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

我 -实际上,类B扩展了类Object,因此,当你在类A中扩展类B时,类A间接扩展了类Object。这是多级继承,而不是多继承。

但是我的回答使他不满意。

我的答案正确吗?还是我在哪里错?内部实际发生了什么?


问题答案:

是的,大多数情况下,当然也可以根据您所描述的情况。这不是多重继承:

就是您所说的,具有多个级别的单一继承。

这是多重继承:从两个或多个彼此没有任何“ is”关系的碱基继承;将从不相关的行继承,或从先前分歧的行继承(在Java中,由于Object始终是基础,因此将是后者):

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

obj.member

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

我上面说“主要”的原因是Java具有接口,而从Java 8开始,它在接口上具有“默认方法”。这会使事情变得复杂了一点,但你对各级答案是你所描述的面试官说关于上下文正确ObjectClassAClassB

在Java中,接口始终使某种事物具有两种不同类型的“是”关系成为可能:继承自的类类型以及实现的几种接口类型中的任何一种。没有默认方法的接口实际上并不是多重继承的(类必须提供实现),但是它们的确使类从不相关的类型树中具有多个“是”关系成为可能。(我不是学术人员,学术人员可能会争辩说他们以学术方式提供多重继承。)

使用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继承doSomethingfrom 的实现ClassA。但它也获得了“默认”版本doSomethingElseInterface1。我们没有在中实现它ClassB,但ClassB不是抽象的:它确实具有doSomethingElse。它从接口获取它。我用这个词“被”,而不是“继承”有,但这个看上去一个很多像继承的默认方法。

这基本上是多重继承的“轻度啤酒”(如“轻啤酒”中的)。它通过真正的多重继承来解决棘手的问题,例如:

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


 类似资料:
  • 本文向大家介绍Java需要多个上限(“扩展A和B”),包括了Java需要多个上限(“扩展A和B”)的使用技巧和注意事项,需要的朋友参考一下 示例 您可以要求通用类型来扩展多个上限。 示例:我们要对数字列表进行排序,但Number不实现Comparable。 在此示例中,T必须扩展Number 并实现Comparable<T>应该适合所有“正常”内置数字实现(例如Integer,BigDecimal

  • 假设我有下面的代码... 不管类ImplementTwo是同时实现B和A,还是只实现B,它仍然需要在接口A中实现方法A(),因为接口B扩展了接口A。有什么理由显式地这样做吗 而不只是 ?

  • 问题内容: 我正在学习Java,但有两个问题: 之间有什么区别? 和 考虑到: 之间有什么区别: (A)x.run_function(); 假设A和B都具有函数,将执行哪个函数? 问题答案: 最重要的区别在于对象的静态和动态类型与对象的引用之间。 说B延伸A,C延伸B。 对象的动态类型(新类型中使用的类型)是其实际的运行时类型:它定义了对象的实际方法。 对象引用(变量)的静态类型是编译时类型:它定

  • 问题内容: 我对使用python list对象感兴趣,但功能略有改变。特别是,我希望列表是1索引而不是0索引。例如: 输出应为:1 但是,当我更改和方法来执行此操作时,出现了错误。我对这些方法进行了很多修改,但这基本上就是我在那里做的: 我想问题是它本身正在调用与定义的方法相同的方法。如果是这样,如何使它使用方法而不是方法?我尝试使用代替,但导致投诉 有任何想法吗?另外,如果您可以为此指出一个好的

  • 我在挣扎。 当扩展一个类时,我可以很容易地向它添加一些新属性。 但是,当我扩展基类时,如果我想向基类的对象(简单对象的属性)添加新属性,该怎么办? 下面是一个带有一些代码的示例。 基类 派生类 现在,正如您可以从行内注释中看到的,这将激怒TypeScript。但这在JavaScript中工作。那么,实现这一目标的正确方法是什么呢?如果没有,问题是在我的代码模式本身吗?什么模式适合这个问题? 也许您

  • 我在下棋。我想做一个抽象的piece类,然后可以通过pawn/knight/rook/等进行扩展。假设我的piece类是这样的: 我希望Pawn具有相同的sayName功能,但我希望它具有不同的movePiece功能,因为Pawn有自己独特的移动方式。我怎么做典当,使它扩展件,并覆盖件的移动件功能?