3

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

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

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

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

(见接受的答案)

4

3 回答 3

8

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

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

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

于 2012-06-04T16:06:28.027 回答
1

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

  • 您正在编写匿名函数(当您的界面只有一种方法并且您像函数式语言中的匿名函数一样使用它时)这没问题,但是这种情况很少见。
于 2012-06-04T16:23:03.963 回答
1

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

/** 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 文件中有太多代码,但也不希望太少。

于 2012-06-04T20:35:56.773 回答