为什么父类和子类都要实现同一个接口?

35

我继承了一些老旧的Java代码(1.4版本),这个设计决策经常出现。我不明白它是否有任何目的或原因。

public interface SoapFacade extends iConfigurable{ }

public class SoapFacadeBase implements SoapFacade{
...
}

public class SoapFacadeImpl extends SoapFacadeBase implements SoapFacade{
...
}
据我理解接口(并通过我的实验加强了这一点),在父类和子类同时实现相同接口没有意义。在这种情况下,SoapFacade 中的所有内容已经在 SoapFacadeBase 中实现,但是 iConfigurable 接口的方法是在 SoapFacadeImpl 中实现的。然而,这并不需要让 SoapFacadeImpl 实现 SoapFacade 接口。

我是否有所不知关于接口的某些内容,使得这种模式有用或者受益?除了缺乏清晰度之外,是否存在其他成本应该进行重构?还是应该为了清晰/简明而进行重构?

4个回答

48
据我所理解的接口(并且我的实验也加强了这一点),在父类和子类都实现相同接口是没有意义的。从技术上讲,它完全是多余的。然而,它确实记录了您打算将SoapFacadeImpl作为SoapFacade实现的事实,并确保如果您(或其他人)决定从基类中删除implements SoapFacade ,则会收到编译错误。
您可以在标准Java集合API的各个地方看到这种模式。ArrayList实现了List,即使其基类(AbstractList)已经实现了List。对于HashSet / AbstractSetSet接口也是如此。

2
它有一些副作用。如果你想用SomethingElse替换SoapFacade(不是重命名SoapFacade,而是用完全不同的接口替换),你必须在所有地方进行替换,而且一些IDE(如Eclipse)的“重构”功能也无法帮助你。此外,如果你将代码传递给其他人,他们可能会花费几分钟时间找出为什么子类(比如:wtf...谁写的这个玩意儿)会出现编译错误。 - gd1
+1 这确实让我对此有了新的思考。从发布的示例中可以看出,SoapFacade 中的所有内容都在基类中实现;因此,我更倾向于从派生类中删除 implements SoapFacade,以便将 SoapFacade 的细节隐藏起来,不让子类知道。 - Riggy
@Giacormo,你说的“在子类上出现编译错误”是什么意思? - aioobe

13
如果您将接口用作标记。 Class.getInterfaces(); 只会返回直接实例化的接口。

0

我认为这种设计是毫无意义的。正如你所说,实现的接口只是被继承了,因此没有必要在子类中复制和粘贴“implements SomeInterface”。

这并不更清晰、更聪明或者更好什么的……


4
即使基类进行重构并不再实现接口,它也确保子类实现了该接口。它还具有文档说明的作用。需要注意的是,在标准集合API中几乎到处都使用它。请查看我的回答。 - aioobe

-2

这是无意义的,不要这样做。

特别是在像Java集合这样的公共API中。这绝对是无意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接