【问题标题】:Why implement interfaces 'A' and 'B', when 'B' extends 'A'当“B”扩展“A”时,为什么要实现接口“A”和“B”
【发布时间】:2014-11-02 22:37:00
【问题描述】:

假设我有以下代码...

interface A{
  void a();
}

interface B extends A{
  void b();
}

class ImplementOne implements B{ 
  public void a(){};
  public void b(){};
}     

class ImplementTwo implements B, A{ 
  public void a(){};
  public void b(){};
} 

不管类ImplementTwo是否同时实现B和A,或者只实现B,它仍然需要在接口A中实现方法a(),因为接口B扩展了接口A。有什么理由明确地这样做

...implements B, A

而不仅仅是

...implements B  

?

【问题讨论】:

  • 除了代码风格之外没有什么特别的原因。
  • 查看现有的遮阳篷:*.com/questions/10839131/…
  • @PieterSchool 这个问题没有回答这个问题,OP 不是在问扩展与实现的区别,而是关于指定多个相互扩展的接口的风格差异。
  • 当有多个默认值可用时,重新实现一个接口是否会改变将使用哪个默认实现?

标签: java class interface


【解决方案1】:

就行为而言,这两种方法没有区别。在字节码信息方面,关于已实现接口的信息存在细微差别。例如:

Class<?>[] interfaces = ImplementTwo.class.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
    System.out.println(interfaces[i]);
}

使用implements B, A 时将返回两个类实例,而使用implements B 时将返回一个实例。

不过,以下使用这两种方法都会返回 true

A.class.isAssignableFrom(ImplementTwo.class)

【讨论】:

  • 有趣的收获和迄今为止唯一不无聊的答案,+1
【解决方案2】:

IMO 您想要明确指定它的唯一原因是,如果您试图让需要与之交互的其他人更容易阅读代码。话虽如此,实际上,像这样的两步间接并不是那么抽象以至于难以理解,所以我真的认为这没有必要发生。

【讨论】:

  • +1 在 JDK 中发生这种情况的一个常见原因是它是在某个时候添加的,并且他们非常不愿意更改这样的内容,以防它破坏某人的代码。即有这么多代码,很可能有人编写了依赖于此的代码,例如通过反射。
  • 我敢打赌,在过去,接口 B 没有扩展 A,后来一些人意识到 B 应该扩展 A。然后他们为那些缺少“a”方法的实现修复了 1 或 2 个编译器错误,而不必费心修改可能已经声明“实现 A、B”的众多类。
【解决方案3】:

最著名的例子是使用接口Serializable

这经常重复的目的是:如果超级接口突然Serializable接口分离,它的子接口仍将保持Serializable,因为它已经定义为Serializable .

这经常发生在代码重构中。除此之外没有区别。

【讨论】:

    【解决方案4】:

    两种变体在语义上完全相同。出于文体原因,您可能更喜欢其中一个(例如,为了让该类的读者立即清楚它同时实现了AB)。

    【讨论】:

      【解决方案5】:

      代码的行为(或编译)方式没有区别。

      有些人更喜欢明确列出所有实现的接口,即使它们是由另一个实现的接口强制执行的。这纯粹是个人/代码风格偏好的问题。

      【讨论】:

        【解决方案6】:

        这两种方法是相同的。在不了解 A-B 层次结构的情况下,您可以选择 implements A, B 而不是 implements B 来指定对象的整个类型列表

        【讨论】:

          【解决方案7】:

          在这种情况下,它没有任何区别。但是从技术上讲,您可以拥有两个彼此不相关的接口,它们具有相同的方法声明。并且此实现将为两个接口实现方法。

          【讨论】:

            最近更新 更多