我知道在 Java 中不允许遵循循环继承层次结构。编译器抛出一个错误,但我真正感兴趣的是知道编译失败的确切原因。
class A extends B{}
class B extends C{}
class C extends A{} // this will give you compile time error.
在我编写代码的那一刻,编译器会抛出错误的原因是什么class C extends A{}
我知道在 Java 中不允许遵循循环继承层次结构。编译器抛出一个错误,但我真正感兴趣的是知道编译失败的确切原因。
class A extends B{}
class B extends C{}
class C extends A{} // this will give you compile time error.
在我编写代码的那一刻,编译器会抛出错误的原因是什么class C extends A{}
这样的关系根本不可能。它定义了一个无限递归类。为了定义class C
,你需要class A
,定义class A
你需要class B
,定义class B
你需要class C
——你又回到了起点。这会无限进行,因此编译器无法做到这一点,而且它也没有逻辑意义。
看看extends这个词,在Java中一个子类确实扩展了它的超类。这意味着子对象是它的所有超级对象加上一些新成员和一些指定成员。
那怎么能
我们可以说扩展是一个顺序关系: A 扩展 B意味着A < B(甚至不是 A <= B),然后在你的情况下B < C,所以很明显C 不能小于 A。
有一个简单的非常实际的问题(除了其他答案中解释的逻辑问题):
类必须在实例化期间初始化。这是在 Java 中通过首先初始化超类来完成的。当您有一个循环时,初始化代码会沿着继承阶梯上升并尝试初始化永远无法到达的超类......
因此,对于 Java,这必须被禁止。
C
自IS-A 以来,我们可以将问题简化为这些语句B
:
class A extends C{}
class C extends A{}
显然这是一个冲突,因此编译器会给出该错误。
循环继承可以有两个例子:
1. A 类扩展 A { } :- 这没有任何意义,因为 A 类的成员已经存在于 A 类中,那么为什么要扩展。
2. A 类扩展 B { } 和 B 类扩展 A { } :- 在这种情况下,两个类的成员都可以写在一个类中,那么为什么要写两个类并相互扩展。
由于上述用例无效,因此 Java 不支持循环继承。
我想我会为这个线程添加一个尚未说明的 Java 特定答案。在 Java 中,每个类最终都必须派生自Object
该类。这就是为什么每个对象都可以Object
毫无问题地转换为实例的原因。为了支持这一事实,Java 继承教程指出:
除了没有超类的 Object 之外,每个类都有一个且只有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐含地是 Object 的子类。
类可以从从类派生的类派生的类派生,依此类推,并最终从最顶层的类 Object 派生。据说这样的类是继承链中所有类的后裔,这些类一直延伸到 Object。
如果允许循环继承依赖,并且因为 Java 中的类必须只有一个直接超类(见上文),那么任何循环依赖链中的类实例(例如,您的类的实例A
、B
和C
)都不能从 继承Object
,即不允许。因此,这些循环依赖对象都不能被视为Object
s。因此,编译器必须禁止循环依赖。