最近,我一直在阅读那些谈论接口是抽象的错误概念的帖子。一个这样的帖子是http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstractions.aspx
我有点困惑。如果我没有接口(接口/抽象类),那么我将如何注入我的依赖项并模拟它们?
另外,我听过人们谈论不使用只有一个实现者的接口。像这里的博客一样 - http://simpleprogrammer.com/2010/11/02/back-to-basics-what-is-an-interface/
现在所有这些,是不是违反了原则 - 编程接口而不是实现?
答案 0 :(得分:6)
对接口而不是实现进行编程更多的是使用数据抽象和封装。
当我们在编程方面对接口说“接口”时。这种接口意味着类的外部方法和属性。它不必是语言级接口。 (关键字界面。)
您应该努力确保您的代码不依赖于其他类的内部细节。
答案 1 :(得分:5)
我会说我不同意链接文章中的许多要点:
接口是合同。合同有两部分 - 方法签名(纯语法)和文档。
接口是抽象。我看不到LSP违规的例子。 IRectangle
示例根本不是一个好例子。关于Set extends Collection
,可以说同样的事情,其中不允许添加重复项。如果您通过Collection
,您可能会感到惊讶,因此不允许重复。使用Collection
接口,通过记录实现者可能添加限制来处理此问题
漏洞抽象是不可避免的。但这完全取决于设计师。而btw“接口是漏洞抽象”意味着他们是抽象。
这些家伙似乎错过了“接触”单元测试。模拟实现是使用接口的一个很好的理由(尽管你也可以模拟具体的类)。
我们当前项目的一个很好的例子 - 最初我们只有一个DAO实现 - 一个从数据库中获取东西。但后来我们将部分操作转换为专用搜索引擎。我们添加了DAO的另一个实现,然后我们去了。因此,最初的一个实现的接口得到了回报。
顺便说一句,最初SortedSet
在JDK中只有一个实现 - TreeSet
。现在它有两个。还有更多来自外部图书馆。
最后,接口(作为一种语言结构)是一种描述类功能的方法,具有禁止任何实现滑入的额外功能。即 - 接口是一种难以滥用的提供抽象的方式。
所有人都说,你不需要任何接口。但这取决于具体情况。例如,我不使用辅助类的接口。这篇文章的有效之处在于“对界面的编程”并不一定包含interface
关键字。一个类的“公共接口”(理论上)是其公共方法的集合。
答案 2 :(得分:3)
只要你不过分,我相信你最好不要创建一个界面。
这是我经常遇到的一个用例,其中只有一个实现者(在我看来)非常好:你有一个Swing组件,假设它是一个CarComparisonResultsPanel
,它允许用户查看结果汽车之间的比较。作为面板的用户,我宁愿使用CarComparisonResult
接口只有getCarSimilarities()
和getCarDifferences()
,而不是实现这些方法的JPanel实现以及其他几十个。
答案 3 :(得分:0)
编程到接口背后的原则不必仅限于接口情况。当你设计你的界面时,你所问的一般问题是“我希望在哪里消费这个?由谁?为了什么目的?”即使在创建实现类时也应该询问的问题。
可能在设计界面时,您会意识到您并不需要将其设置为接口,并且允许重载和继承就足以进行测试。正如第一篇文章所提到的那样,如果你总是以对象和接口之间的1:1关联结束,除了“我正在编程接口”之外没有任何目的,你只是弄乱了你的代码。
但是,这并不意味着您无法继续设计类,就好像您正在为它创建一个接口/基类,使用一组提供基本功能的通用方法/属性/字段然后添加其他更具体的实现方法/属性/字段。这样做仍然是IMO,属于编程接口的原则。当一个明确的需求出现时,它肯定会为您提供一个接口/基类的门。