我知道Java中不允许使用循环继承层次结构。编译器会抛出错误,但我真正感兴趣的是知道编译失败的确切原因。
class A extends B{}
class B extends C{}
class C extends A{} // this will give you compile time error.
当我编写代码class C extends A{}
答案 0 :(得分:9)
这种关系根本不可能。它定义了一个无限递归类。要定义class C
,您需要class A
,定义您需要的class A
class B
,并定义您需要的class B
class C
- 以及你回到了起点。这种情况无穷无尽,因此编译器无法做到这一点,也没有逻辑意义。
答案 1 :(得分:3)
只要看一下 extends 这个词,在Java中,一个子类真的扩展它的超类。这意味着子对象是它的所有超级对象加上一些新成员和一些指定成员。
那怎么可以
我们可以说扩展名是Order Relation所以: A延伸B 表示 A< B (甚至不是A< = B),然后在你的情况下 B< C ,所以很明显 C不能小于A 。
答案 2 :(得分:3)
有一个非常实际的问题(除了在其他答案中解释的逻辑问题):
必须在实例化期间初始化类。这是通过首先初始化超类在Java中完成的。当你有一个循环时,初始化代码会继承继承阶梯,并尝试初始化从未到达的超类......
因此,对于Java,必须禁止这样做。
答案 3 :(得分:1)
自C
IS-A B
以来,我们可以将问题减少到这些陈述中:
class A extends C{}
class C extends A{}
显然这是冲突,因此编译器会给出错误。
答案 4 :(得分:1)
让我们抽象出对家族树的继承概念。从本质上讲,这是他们归结为的。我将在这里使用反向映射方案,因此我将从C到A工作。
在Java中,这导致:
采用逻辑极值,这将包括multiple inheritance,这是Java不支持的功能,但可以通过使用interfaces来缓解。
你的遗产计划所说的是祖父直接从孙子身上继承,这没有任何意义。
答案 5 :(得分:0)
循环继承可以有两个例子:
1. A类延伸A {}: - 这没有任何意义,因为A类的成员已经存在于A类中,那么为什么要扩展。
2. A类扩展B {},B类扩展A {}: - 在这种情况下,两个类的成员可以写在一个类中,然后为什么要编写两个类并相互扩展。
由于上面的用例是无效的,因此Java不支持循环继承。
答案 6 :(得分:0)
我认为我会在这个帖子中添加一个尚未说明的Java特定答案。在Java中,每个类最终都必须从Object
类派生。这就是为什么每个对象都可以毫无问题地转换为A
实例的原因。为支持这一事实,Java Inheritance Tutorial州:
Excepting Object,没有超类,每个类都有一个且只有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐式地是Object的子类。
类可以从派生自类的类派生的类派生,依此类推,最终派生自最顶层的类Object。据说这样的类是继承链中延伸回Object的所有类的后代。
如果允许循环继承依赖,并且因为Java中的类必须只有一个直接超类(参见上文),那么任何循环依赖链中的类实例(例如,类B
的实例,{{1 }}和C
)无法从Object
继承,这是不允许的。因此,这些循环依赖关系对象都不能被视为Object
。因此,编译器必须禁止循环依赖。