为什么坚持接口的所有实现都扩展了基类?

Jam*_*unn 26 java inheritance abstract-class interface hamcrest

我只是看着GitHub上的Java Hamcrest代码,并注意到他们采用了一种似乎不直观和笨拙的策略,但它让我想知道我是否遗漏了一些东西.

我在HamCrest API中注意到有一个接口Matcher和一个抽象类BaseMatcher.Matcher接口使用此javadoc声明此方法:

    /**
     * This method simply acts a friendly reminder not to implement Matcher directly and
     * instead extend BaseMatcher. It's easy to ignore JavaDoc, but a bit harder to ignore
     * compile errors .
     *
     * @see Matcher for reasons why.
     * @see BaseMatcher
     * @deprecated to make
     */
    @Deprecated
    void _dont_implement_Matcher___instead_extend_BaseMatcher_();
Run Code Online (Sandbox Code Playgroud)

然后在BaseMatcher中,此方法实现如下:

    /**
     * @see Matcher#_dont_implement_Matcher___instead_extend_BaseMatcher_()
     */
    @Override
    @Deprecated
    public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
        // See Matcher interface for an explanation of this method.
    }
Run Code Online (Sandbox Code Playgroud)

不可否认,这既有效又可爱(令人难以置信的尴尬).但是,如果每个实现Matcher的类都是为了扩展BaseMatcher,那么为什么要使用一个接口呢?为什么不首先让Matcher成为一个抽象类,让所有其他匹配器扩展它?以Hamcrest的方式做这件事有什么好处吗?或者这是不良做法的一个很好的例子?

编辑

一些好的答案,但为了寻找更多的细节,我正在提供赏金.我认为向后/二进制兼容性的问题是最好的答案.但是,我希望看到更多的兼容性问题,理想情况下是一些代码示例(最好是Java).另外,"向后"兼容性和"二进制"兼容性之间是否有细微差别?

进一步编辑

2014年1月7日 - pigroxalot在下面提供了一个答案,链接到 HamCrest的作者对Reddit评论.我鼓励每个人阅读它,如果你发现它提供了信息,请upvote pigroxalot的回答.

即便进一步编辑

2017年12月12日 - pigroxalot的答案以某种方式被删除,不知道是怎么回事.这太糟糕了......简单的链接非常有用.

ajb*_*ajb 10

git log有这个条目,从12月(初始签入后约9个月)2006年:

添加了所有Matchers应该扩展的抽象BaseMatcher类.随着Matcher接口的发展,这允许未来的API兼容性[原文如此].

我没有试图弄清楚细节.但是,随着系统的发展,保持兼容性和连续性是一个难题.它确实意味着,如果你从头开始设计整个产品,有时你最终会得到一个永远不会创造的设计.


Nie*_*jes 5

但是,如果每个实现Matcher的类都是为了扩展BaseMatcher,那么为什么要使用一个接口呢?

这不完全是意图.抽象基类和接口从OOP角度提供完全不同的"契约".

一个接口是一个通信协议.接口由类实现,以向世界表明它遵守某些通信标准,并且将响应具有特定参数的特定呼叫给出特定类型的结果.

一个抽象基类执行合同.抽象基类由类继承,以提供基类所需的功能,但留给实现者提供.

在这种情况下,两者都重叠,但这只是一个方便的问题 - 接口是你需要实现的,而抽象类是为了使接口更容易实现 - 没有任何要求使用该基类是能够提供界面,只是为了减少工作量.您绝不限于为自己的目的扩展基类,不关心接口契约,或实现实现相同接口的自定义类.

在老式的COM/OLE代码和其他框架中,给定的实践实际上相当普遍,这些框架有助于进程间通信(IPC),它将实现与接口分离成为基础 - 这正是这里所做的.