循环继承和接口 - 当B类实现A接口时,A类不能实现B类接口

时间:2015-11-25 13:41:24

标签: java android inheritance interface implements

我有:

public class A implements BListener {
    public interface AListener {}
}

public class B implements AListener {
    public interface BListener {}
}

因此,如果我理解正确,则会发生循环继承,因为:

编译器转到 A 并说“嘿,A实现BListener,让我们去找BListener!”

然后当它试图找到BListener时,它最终会进入 B ,它说:

“嘿,BListener,A需要在B里面!但是等待!B需要AListener!让我们去找AListener!”

然后它到达A,重复一遍。我做对了吗?

顺便说一下,这个编译错误发生在Android开发上。

2 个答案:

答案 0 :(得分:6)

它可能有助于把它画出来。

              >A 
is part of  /     \    inherits
                   V             
   AListener        BListener
           ^
  inherits  \     /    is part of 
               B<

一个可爱的圈子。如果没有已存在的其他人,则无法创建其中一个。

  

编译器是否是咖啡追逐它自己的尾巴的ADHD高的松鼠?

不,因为松鼠不会停止(直到咖啡因用完为止)。编译器会查找它,然后放弃。

注意:Eclipse有一个允许此设置的错误。

答案 1 :(得分:2)

经过进一步调查,我最初错了。

您注意到的行为的技术说明如下:

来自Superclasses and subclasses

的Java语言规范章节
  

如果C中提及T,则T类直接取决于类型extends   implements的{​​{1}}或C条款要么作为超类,要么作为超类   超级接口,或作为完全限定形式的限定符   超类或超接口名称。

     

如果以下任何一项,则课程C取决于引用类型T   真:

     
      
  • C直接取决于T
  •   
  • C直接依赖于I上依赖({9.1})的接口T
  •   
  • C直接依赖于依赖D的类T(递归使用此定义)。
  •   
     

如果某个类依赖于自身,那么这是一个编译时错误。

假设类在包com.example中声明,让我们使用您的代码,使用类型用途的完全限定名称:

public class A implements com.example.B.BListener {
    public interface AListener {}
}

public class B implements com.example.A.AListener {
    public interface BListener {}
}

遵循上述JLS的规则

  • A直接取决于BListener,因为它在implements条款中有提及。
  • A直接依赖于B,因为它在超级接口的完全限定名称中被提及为限定符(BListenercom.example.B.BListener
  • B直接取决于AListener,因为它在implements条款中有提及。
  • B直接依赖于A,因为它在超级接口的完全限定名称中被提及为限定符(AListenercom.example.A.AListener
  • A直接取决于取决于B的{​​{1}}。

因此A取决于A,并且应该发生编译错误。

在Eclipse中,如果您限定名称

,则会发生错误
A

但是,如果您使用class A implements B.BListener { public static interface AListener { } } class B implements A.AListener { public static interface BListener { } } 语句,则不会。我将与他们打开一个错误。