接口(接口/抽象类)不是抽象?

发布于 2024-10-06 10:29:23 字数 520 浏览 5 评论 0原文

最近,我一直在阅读一些帖子,其中讨论了接口是抽象的错误观念。其中一篇文章是 http://blog.ploeh.dk/2010/12/02 /InterfacesAreNotAbstractions.aspx

我有点困惑。如果我没有接口(接口/抽象类),那么我将如何注入我的依赖项并模拟它们?

另外,我听人们谈论不要使用只有一个实现者的接口。喜欢这个博客 - http://simpleprogrammer .com/2010/11/02/back-to-basics-what-is-an-interface/

现在这一切,不是违反了原则 - 编程到接口而不是实现吗?

Of late, I have been reading posts which talks about the supposed wrong notion that interfaces are abstractions. One such post is http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstractions.aspx

I am a bit confused. If I don't have interfaces (interface/abstract class), then how will I inject my dependencies and mock them?

Also, I have heard people talk about not using interfaces which has just one implementor. Like this blog here - http://simpleprogrammer.com/2010/11/02/back-to-basics-what-is-an-interface/

Now all this, doesn't it violate the principle - Program to an interface and not implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

空‖城人不在 2024-10-13 10:29:23

对接口而不是实现进行编程更多的是使用数据抽象和封装。

当我们说“接口”时,指的是接口编程。这种接口意味着类的面向外部的方法和属性。它不一定是语言级界面。 (关键字interface。)

您应该努力确保您的代码不依赖于其他类的内部细节。

Programming to an interface instead of an implementation is more about using data abstraction and encapsulation.

When we say "interface" in terms of programming to an interface. That kind of interface means the external facing methods and properties of a class. It doesn't have to be a language level interface. (The keyword interface.)

You should be striving to make sure that your code is not dependent on the internal details of other classes.

卷耳 2024-10-13 10:29:23

我想说我不同意链接文章中的许多观点:

  • 接口契约。该合约有两部分 - 方法签名(纯粹的语法)和文档

  • 接口抽象。我看不到 LSP 违规的例子。 IRectangle 示例根本不是一个好示例。对于 Set extends Collection 也可以这样说,其中不允许添加重复项。如果您传递给Collection,您可能会惊讶它不允许重复。对于Collection接口,这是通过记录实现者可以添加限制

    来处理的,

  • 泄漏抽象是不可避免的。但这完全取决于设计师。顺便说一句,“接口是泄漏抽象”意味着它们是抽象。

  • 这些人似乎错过了“接触”单元测试的机会。模拟实现是使用接口的一个很好的理由(尽管您也可以模拟具体类)。

  • 我们当前项目中的一个非常好的例子 - 最初我们只有一个 DAO 实现 - 一个从数据库中获取内容。但后来我们把一些操作改成了专门的搜索引擎。我们添加 DAO 的另一个实现,然后就可以了。因此,拥有一个具有一种实现的接口最初是有回报的。

    这是

  • 顺便说一句,最初 SortedSet 在 JDK 中只有一个实现 - TreeSet。现在有两个了。还有更多来自外部库的内容。

  • 最后,接口(作为一种语言构造)是一种描述类功能的方法,具有不允许插入任何实现的额外功能。也就是说,接口是一种很难滥用的提供抽象的方式。

话虽如此,您并不需要为所有事情提供接口。但这取决于具体情况。例如,我不使用辅助类的接口。文章的一个有效观点是“接口编程”不一定包含 interface 关键字。类的“公共接口”(理论上)是其公共方法的集合。

I'd say I disagree with many of the points in the linked articles:

  • interfaces are contracts. The contract has two parts - the method signature (purely syntactic) and the documentation.

  • interfaces are abstractions. I couldn't see an example of LSP violation. The IRectangle example is not a good one at all. The same thing can be said about Set extends Collection, where adding duplicates is disallowed. If you are passed a Collection you might be surprised it disallows duplicates. With the Collection interfaces this is taken care of by documenting that implementors may add restrictions

  • Leaky abstractions are inevitable. But this entirely depends on the designer. And btw "interfaces are leaky abstractions" means they are abstractions.

  • The guys seem to have missed "exposure" to unit-testing. Mock implementations are a very good reason to use an interface (although you can mock concrete classes as well).

  • A very good example from our current project - initially we has only one DAO implementation - one taking stuff form the database. But later we switched some of the operations to a dedicated search engine. We add another implementation of the DAO, and there we go. So having an interface with one implementation initially paid off.

  • Btw, initially SortedSet had only one implementation in the JDK - TreeSet. Now it has two. And many more from external libraries.

  • finally, interfaces (as a language construct) are a way to describe a class' functionality with the extra feature of disallowing any implementation slipping in. That is - interfaces are a hard to misuse way of providing abstraction.

That all said, you don't need an interface for everything. But it depends on the concrete case. I, for example, don't use interfaces for helper classes. And a valid point of the articles is the "programming to an interface" does not necessarily include the interface keyword. The "public interface" of a class is (theoretically) the set of its public methods.

我喜欢麦丽素 2024-10-13 10:29:23

只要你不过分,我相信你最好创建一个界面。

这是我经常遇到的一个用例,其中只有一个实现者(在我看来)完全没问题:您有一个 Swing 组件,假设它是一个 CarComparisonResultsPanel,它允许用户查看汽车之间的比较。作为面板的用户,我宁愿拥有一个仅包含 getCarSimilarities()getCarDifferences()CarComparisonResult 接口,而不是 JPanel 实现实现这些方法以及许多其他方法。

编辑:为了让我的“不要过度做”的观点更清楚一些,这些是一些过度做的例子:工厂、构建器、帮助器/实用程序类的接口、不向其父级添加相关公共方法的 GUI 组件, ...

As long as you don't overdo it, I believe you're better off creating an interface.

Here's a use case I frequently have where having only one implementor is (in my opinion) perfectly fine: you have a Swing component, let's say it's a CarComparisonResultsPanel, which allows the user to see the results of the comparison between cars. As a user of the panel, I'd rather have a CarComparisonResult interface with just getCarSimilarities() and getCarDifferences() than a JPanel implementation that implements those methods as well as dozens of others.

EDIT: To make my "don't over do it" point a bit clearer, these are some examples of overdoing it: interfaces for Factories, Builders, Helper/Utility classes, GUI components that don't add relevant public methods to their parent, ...

离笑几人歌 2024-10-13 10:29:23

接口编程背后的原则不必仅限于仅接口的情况。当您设计界面时,您提出的一般问题是“我期望在哪里使用它?由谁使用?以及用于什么目的?”即使在创建实现类时也应该提出的问题。

可能在设计接口时,您会意识到实际上并不需要将其设为接口,并且允许重载和继承就足以进行测试。正如第一篇文章提到的,如果您始终以对象和接口之间的 1:1 相关性结束,而除了“我正在针对接口进行编程”之外没有其他目的,那么您只是把代码弄得一团糟。

但是,这并不意味着您不能继续设计该类,就像为它创建一个接口/基类一样,使用一组提供基本功能的通用方法/属性/字段,然后添加其他方法/更具体于实现的属性/字段。在我看来,这样做仍然符合接口编程的原则。当出现明确的需求时,它肯定也会为您打开提取接口/基类的大门。

The principles behind programming to an interface don't have to be left to interface only situations. When you're designing your interfaces, the general questions you're asking are "Where am I expecting this to be consumed? By whom? And to what purpose?" Questions that should be asked even when creating implementation classes.

It might be that, while designing an interface, you come to the realization that you don't really need to make this an interface, and allowing overloading and inheriting will suffice for testing. As the first article mentioned, if you're consistently ending up with a 1:1 correlation between objects and interfaces with no purpose other than "I'm programming against interfaces," you're just making a mess of your code.

But, that doesn't mean you can't go ahead and design the class as if you were creating an interface/base class for it, with a set of generic methods/properties/fields that provide base functionality and then add other methods/properties/fields more specific to the implementation. Doing so would still, IMO, fall within the principles of programming to an interface. It would, also, certainly leave the door open for you to extract an interface/base class when a clear and definite need arose.

醉酒的小男人 2024-10-13 10:29:23

您可以有两种不同风格的抽象,它们是:

  1. 垂直(“Is-a”关系)
  2. 水平(方法)

当我们以编程方式决定使用更通用的类型而不是更具体的类型时,在开发阶段,我们将抽象引入代码中,因为在运行时使用哪个具体实现(例如依赖注入、方法声明)并不重要。

沿着这些思路,我们使用接口和抽象类来实现更好的泛化和松散耦合。

另一种可能性是通过调用方法,因为消费应用程序(客户端)只会使用功能/服务,这是在隐藏的另一个类中进行的实现。

输入图片此处描述

You can have abstraction in two different flavors, which are:

  1. vertical ( “Is-a” relationship )
  2. horizontal ( methods )

When programmatically we decide for more generic types instead of more specific types, during the development phase, we bring abstraction to the code, because it doesn't matter at runtime which concrete implementation will be used (e.g. dependency injection, method declaration).

Along these lines, we use interfaces and abstract classes for greater generalization and loose coupling.

Another possibility would be by invoking a method, as the consuming application (client-side) would only use the functionality/service, being the implementation made within another class hidden from it.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文