为什么坚持接口的所有实现都扩展基类?
我只是在GitHub上查看Java Hamcrest代码,并注意到他们采用了一种似乎不直观和尴尬的策略,但它让我怀疑我是否遗漏了什么。
我注意到在HamCrest API中有一个接口匹配器和一个抽象类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_();
然后在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.
}
诚然,这既有效又可爱(而且非常尴尬)。但是,如果意图是每个实现 Matcher 的类也扩展 BaseMatcher,那么为什么要使用接口呢?为什么不首先让 Matcher 成为一个抽象类,并让所有其他匹配器扩展它呢?像Hamcrest那样做这件事有什么好处吗?或者这是不良做法的一个很好的例子?
编辑
一些很好的答案,但为了寻找更多细节,我提供了赏金。我认为向后/二进制兼容性问题是最好的答案。但是,我希望看到更多关于兼容性的问题,最好是使用一些代码示例(最好是Java)。此外,“向后”兼容性和“二进制”兼容性之间是否存在细微差别?
进一步编辑
2014年1月7日 -- pigroxalot在下面提供了答案,并链接到HamCrest作者在Reddit上的评论。我鼓励大家阅读它,如果你觉得它内容丰富,请投票支持猪侠的答案。
进一步编辑
2017年12月12日 -- pigroxalot的答案不知何故被删除了,不知道这是怎么回事。太糟糕了...这个简单的链接非常翔实。