4

我知道在 Java 中不允许遵循循环继承层次结构。编译器抛出一个错误,但我真正感兴趣的是知道编译失败的确切原因。

class A extends B{}
class B extends C{}
class C extends A{}  // this will give you compile time error.

在我编写代码的那一刻,编译器会抛出错误的原因是什么class C extends A{}

4

7 回答 7

12

这样的关系根本不可能。它定义了一个无限递归类。为了定义class C,你需要class A,定义class A你需要class B,定义class B你需要class C——你又回到了起点。这会无限进行,因此编译器无法做到这一点,而且它也没有逻辑意义。

于 2012-12-10T06:39:36.873 回答
3

看看extends这个词,在Java中一个子类确实扩展了它的超类。这意味着子对象是它的所有超级对象加上一些新成员和一些指定成员。

那怎么能

  • A 是 B 的扩展
  • B 是 C 的扩展
  • C 是 A 的扩展?

我们可以说扩展是一个顺序关系A 扩展 B意味着A < B(甚至不是 A <= B),然后在你的情况下B < C,所以很明显C 不能小于 A

于 2012-12-10T06:47:01.557 回答
3

有一个简单的非常实际的问题(除了其他答案中解释的逻辑问题):

类必须在实例化期间初始化。这是在 Java 中通过首先初始化超类来完成的。当您有一个循环时,初始化代码会沿着继承阶梯上升并尝试初始化永远无法到达的超类......

因此,对于 Java,这必须被禁止。

于 2012-12-10T06:56:33.063 回答
1

让我们将继承的概念抽象到家谱中。从本质上讲,这就是他们归结为的原因。我将在此处使用反向映射方案,因此我将按照从 C 到 A 的方式工作。

  • 你从你的母亲那里继承了某些属性。
  • 你的母亲继承了她父亲的某些特质。
  • 你的祖父可以被认为是继承链中的最高者。

在 Java 中,这会导致:

  • C 继承自 B。
  • B 继承自 A。
  • A 是继承链中的最高对象。

从逻辑上讲,这将包括多重继承,这是 Java 不支持的功能,但可以通过使用接口来缓解。

你的继承方案说的是祖父直接从孙子那里继承,这是没有意义的。

于 2012-12-10T06:54:29.090 回答
1

C 自IS-A 以来,我们可以将问题简化为这些语句B

class A extends C{}
class C extends A{}

显然这是一个冲突,因此编译器会给出该错误。

于 2012-12-10T06:39:05.127 回答
0

循环继承可以有两个例子:
1. A 类扩展 A { } :- 这没有任何意义,因为 A 类的成员已经存在于 A 类中,那么为什么要扩展。
2. A 类扩展 B { } 和 B 类扩展 A { } :- 在这种情况下,两个类的成员都可以写在一个类中,那么为什么要写两个类并相互扩展。
由于上述用例无效,因此 Java 不支持循环继承。

于 2016-09-21T10:55:08.477 回答
0

我想我会为这个线程添加一个尚未说明的 Java 特定答案。在 Java 中,每个类最终都必须派生自Object该类。这就是为什么每个对象都可以Object毫无问题地转换为实例的原因。为了支持这一事实,Java 继承教程指出:

除了没有超类的 Object 之外,每个类都有一个且只有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐含地是 Object 的子类。

类可以从从类派生的类派生的类派生,依此类推,并最终从最顶层的类 Object 派生。据说这样的类是继承链中所有类的后裔,这些类一直延伸到 Object。

如果允许循环继承依赖,并且因为 Java 中的类必须只有一个直接超类(见上文),那么任何循环依赖链中的类实例(例如,您的类的实例ABC)都不能从 继承Object,即不允许。因此,这些循环依赖对象都不能被视为Objects。因此,编译器必须禁止循环依赖。

于 2017-09-14T21:51:25.443 回答