为什么Java禁止继承内部接口?

Phi*_*sky 19 java inheritance dependencies cyclic

即为什么以下"循环依赖"不可能?

public class Something implements Behavior {
    public interface Behavior {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

由于接口不引用外部类,因此应该允许; 但是,编译器迫使我在类外定义那些接口.这种行为有合理的解释吗?

irr*_*ble 11

规范中的相关规则:

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.4

如果在C的extends或implements子句中提到T作为超类或超接口,或者作为超类或超接口名称的限定符,则类C直接依赖于类型T.

http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.1.3

如果在I的extends子句中提到T作为超接口或作为超接口名称中的限定符,则接口I直接依赖于类型T.

因此,如果A extends|implements B.C,A取决于CB.Spec然后禁止循环依赖.

包含B在依赖中的动机尚不清楚.正如你所提到的,如果B.C提升到最高级别C2,就类型系统而言,并没有太大的不同,那么为什么A extends C2可以,但不是A extends B.C吗?B.C虽然嵌套类型确实有一些对B内容的访问权限,但我找不到任何令人A extends B.C麻烦的规范.

唯一的问题是什么时候C是一个内部阶级.假设B=A,A extends A.C应该被禁止,因为存在"封闭实例"的循环依赖.这可能是真正的动机 - 禁止外部类继承内部类.实际的规则更加通用,因为它们更简单,并且即使对于非内部类也是很有意义的.


Jer*_*nce 9

想象一下你是编译器.

我们说你要创建一个类Something.这个类实现了行为......但是行为还不存在,因为Something尚未注册...

你明白这个问题吗?

将class视为包含内容的框.行为包含在Something框中.但是某些东西不存在.

  • 如果问题是关于C++的话,这将是一个有效的答案. (3认同)
  • @PhilipK我不是在谈论实例:我在谈论课程.内部接口位于其封闭类的名称空间中,因此为了能够引用它,需要加载封闭类,并且因为它引用了它的封闭接口而无法加载它. (3认同)
  • 在你的情况下,你显然没有从某个地方导入"行为".让我们假设您的类Something在包"my.fancy.pack"中,然后Somthing的全名是"my.fancy.pack.Something".所以,在你的"工具"部分你基本上写:class my.fancy.pack.Something实现my.fancy.pack.Behaviour".但你的界面是:"my.fancy.pack.Something.Behaviour"!因此作为Jeromy正确地指出编译器无法使用"隐含"名称找到您的行为. (2认同)