【问题标题】:Interface with inner implementation - good or bad [closed]与内部实现的接口 - 好或坏[关闭]
【发布时间】:2012-06-04 16:01:46
【问题描述】:

我正在开发一个包含许多 someInterface - someInterfaceImpl-pairs 的项目。几天前,我有了将默认实现包含为内部类的想法(可能是通过阅读一些客观的 c 代码得到启发)。 现在一些同事(都比我有更多的 Java 经验)看到了这个想法 - 反馈介于震惊和惊讶之间(“这有效吗?”)。

我用谷歌搜索了一下,但没有找到太多证据证明这种“模式”有用(我个人喜欢它): pdf-papera faq about code style

您怎么看 - 特别是在“默认”实现与接口紧密耦合的情况下。

更新 我刚刚发现这个:Java Interface-Implementation Pair

(查看已接受的答案)

【问题讨论】:

    标签: java interface coding-style


    【解决方案1】:

    接口的全部意义在于将用户与实现分开(默认与否)。您可以通过将实现包含为内部类来解决此问题。您并没有真正保存任何代码行,并且使 API 变得混乱。您最终不得不做一些事情来向界面的用户隐藏内部类,例如将其设为私有或默认范围,这可能会更好地避免。此外,如果您的默认实现需要更改,但您已将接口作为 API 的一部分发布,该怎么办。这是一个坏主意,因为它没有太多好处,而且是一种反模式。

    最后,如果您真的有一个默认实现,那么它可能应该是一个基类(而不是一个接口),而其他实现扩展该类并覆盖行为。

    我认为这篇文章对类似问题进行了有趣的讨论: Question

    【讨论】:

    • 如果默认实现需要更改,那么您将放弃使用新实现的版本——这不需要更改接口定义本身。如果它打算用作默认实现,您也不需要隐藏实现。我没有看到按照 OP 描述的方式进行操作的任何 优点,但我也没有看到您提出的负面因素非常可怕——我只是认为这没有意义将它们组合在一起并强制一个新的接口发行版以更改实现。
    • 我正要添加一个关于基本实现 vs 抽象 vs 接口的答案,你打败了我:-)
    • 可怕,也许不是。不好,是的。它打破了接口是非实现 API 的整个概念。如果不出意外,它会降低接口的源代码的可读性,因为它包含一个默认实现,应该对接口的用户隐藏。
    • 你是对的,但在我的特殊情况下,创建接口的唯一原因是可测试性(gwt 与 mvp 模式)。所以api永远不会被“发布”,很可能除了模拟之外永远不会有另一个实现。除此之外 - 有人读过我提供的链接吗?好像还有其他优势?!
    【解决方案2】:

    如果您的默认实现相当琐碎并且可能保持这种方式并且如果没有扩展它或可能扩展它,这可能是要走的路。你不想把它放在它自己的文件中,你还会把它放在哪里?我建议使用公共实例将课程设为私有(假设没有状态):

    /** An interface a lot like java.util.Collection. */
    public interface WhatEver  {
        private class Default  implements Whatever  {
            // Methods...
        }
        /** A default implementation that is always empty.  Suitable as a NULL value. */
        public final WhatEver  DEFAULT = new Default();
        // Rest of interface...
    

    我认为这对执行没有任何影响(类实例中没有数据),但您会得到更好的 Javadoc。您可以使用匿名类并节省一行代码。

    您甚至可能想要一些其他“默认”实例。对于类似集合的界面,您可能有一个具有单个默认条目或无限数量(hasNext 始终返回 true)的相同默认条目。

    我认为关键是默认实现不能依赖于接口之外的任何东西。不使用外部类和接口,除非它们在接口的主体中被引用,并且不使用扩展默认值的外部类。接口变得比接口的标准概念多一点,但仍然独立存在。

    另一个关键点是您不希望在一个 .java 文件中包含太多代码,但也不希望太少。

    【讨论】:

      【解决方案3】:

      我同意上面的答案,但在某些情况下,包括实现是合乎逻辑的,例如:

      • 您正在编写匿名函数(当您的接口只有一个方法并且您像函数式语言中的匿名函数一样使用它时)这没问题,但这种情况很少见。

      【讨论】:

      • Radio 2 不是具有默认实现的接口定义,而是具有被覆盖的默认实现的abstract class 的扩展。请注意,由于提供了默认实现,因此它是作为 abstract class 而不是 interface
      • 同样,ModifyListener 接口没有默认实现。您已经创建了一个实现该接口的匿名内部类。
      • 这就是我要说的。问题是关于内部类的,他没有说明是否匿名。
      • 这很重要:-) - 但我不是在谈论匿名课程。我说的是“combo.addModifyListener(new ModifyListener.Impl())”
      • 啊。我又读了一遍这个问题。不知怎的,我错过了最后一句话,谢谢指出。
      猜你喜欢
      • 2013-08-15
      • 2021-12-11
      • 2012-01-04
      • 2012-09-02
      • 1970-01-01
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 2018-05-12
      相关资源
      最近更新 更多