简体   繁体   English

为什么任何类型的抽象都使用接口而不是抽象类?

[英]Why does any kind of abstraction use interfaces instead of abstract classes?

Heyho, Heyho,

There´sa question in my mind for some time now, which hopefully can be cleared quickly by some of you: 我心中有一段时间有一个问题,希望你们中的一些人可以迅速解决这个问题:

I am a big fan of MVC, ASP.Net Mvc in my case. 在我的案例中,我是MVC,ASP.Net Mvc的忠实粉丝。

What I have noticed is the hype about interfaces. 我注意到的是关于接口的炒作。 Every video, tutorial and book seems to solve any kind of abstraction with interfaces. 每个视频,教程和书籍似乎都可以通过接口解决任何类型的抽象问题。 I have adapted these patterns, understood why and how and I am basically very happy with it. 我已经调整了这些模式,理解了为什么以及如何,我基本上对它非常满意。

But I just don´t get why interfaces are used everywhere. 但我不明白为什么界面到处使用。 I´ve almost never seen some abstraction being done with abstract base classes, which I don´t understand. 我几乎从未见过抽象基类的抽象,我不明白。 Maybe I miss something? 也许我想念一些东西? I know that you can only inherit from one base class while multiple interfaces are possible. 我知道你只能从一个基类继承而多个接口是可能的。 But interfaces do have disadvantages, especially when some changes need to be done, which breaks your implementations. 但是接口确实有缺点,特别是当需要进行一些更改时,这会破坏您的实现。 In my projects so far, I only used to pick interfaces for completely different classes. 到目前为止,在我的项目中,我只习惯为完全不同的类选择接口。

For example, the whole repository pattern could be done with an abstract base class, still providing testability and exchangeability, or did I miss something? 例如,整个存储库模式可以使用抽象基类完成,仍然提供可测试性和可交换性,还是我错过了什么?

Please point me to the part where my brain laggs :) 请指出我脑子滞后的部分:)

Interfaces are used in tutorials, blogs and elsewhere because those authors are particularly influenced by a group of methodology called "design for testability". 接口用于教程,博客和其他地方,因为这些作者特别受到一组称为“可测试性设计”的方法的影响。

Primarily, design for testability school of thoughts used interface every way because they want to be able to mock any component under tests. 首先,可测试性学校的设计使用各种方式的接口,因为他们希望能够模拟测试中的任何组件。 If you use concrete class, then a lot of mocking tools can't mock those class, and hence will make it difficult to test your code. 如果你使用具体的类,那么很多模拟工具都无法模拟这些类,因此会很难测试你的代码。

A Story 一个故事

I once attended a Java user group meeting where James Gosling (Java's inventor) was the featured speaker. 我曾经参加过Java用户组会议,其中James Gosling(Java的发明者)是特色演讲者。 During the memorable Q&A session, someone asked him: "If you could do Java over again, what would you change?" 在令人难忘的问答环节中,有人问他:“如果你能再次做Java,你会改变什么?” "I'd leave out classes," he replied. “我会把课程留下来,”他回答道。 After the laughter died down, he explained that the real problem wasn't classes per se, but rather implementation inheritance (the extends relationship). 在笑声消失之后,他解释说真正的问题不是类本身,而是实现继承(扩展关系)。 Interface inheritance (the implements relationship) is preferable. 接口继承(implements关系)是首选。 You should avoid implementation inheritance whenever possible. 您应该尽可能避免实现继承。

While using only or mostly Interfaces does have code reuse problems(as well as eliminating nice base classes), It makes it a lot easier to do Multiple Inheritance like things. 虽然仅使用或主要使用Interfaces确实存在代码重用问题(以及消除了很好的基类),但它使得像事物这样的多重继承变得容易得多。 As well as having widely different implementations that will work and where you don't have to worry about the base class changing or even what it does(you do have to implement the whole thing though so its a trade off). 除了具有广泛不同的实现,它们将起作用,您不必担心基类更改甚至它所做的事情(您必须实现整个事情,所以它的权衡)。

PS I think the new Go language is based on interfaces rather then inheritance(looks sort of interesting). PS我认为新的Go语言基于接口而不是继承(看起来很有趣)。

If the language doesn't support multiple inheritance or mix-ins abstract base classes are limited in scope compared to interfaces. 如果语言不支持多继承或混合,则与接口相比,抽象基类的范围有限。 Eg in .NET if you must inherit from some other type such as MarshalByRef, you can't use an abstract base class to implement a pattern. 例如,如果必须从MarshalByRef等其他类型继承,则在.NET中,不能使用抽象基类来实现模式。 Interfaces do not impose this restriction. 接口不会施加此限制。

除了您提到的事实,您只能从一个基类继承(如果您想使用已经从具有新框架基类的某个类继承的现有类,这非常不方便),您还可以避免脆弱的基类问题如果您使用接口而不是。

Read about interfaces, abstract classes, breaking changes, and MVC here: http://ayende.com/Blog/archive/2008/02/21/Re-Versioning-Issues-With-Abstract-Base-Classes-and-Interfaces.aspx . 阅读有关接口,抽象类,重大更改和MVC的信息: http//ayende.com/Blog/archive/2008/02/21/Re-Versioning-Issues-With-Abstract-Base-Classes-and-Interfaces。 aspx

One solution that is presented there (or somewhere else on Ayende's blog) is: do use interface but also provide abstract classes. 在那里(或在Ayende的博客上的其他地方)呈现的一个解决方案是:使用界面但也提供抽象类。 Those who case about breaking changes can base their implementations on abstract classes. 那些关于破坏变化的人可以将他们的实现基于抽象类。 Those who need power of interfaces are also satisfied. 那些需要接口电源的人也很满意。 But do make sure your methods accept interfaces, not abstract classes, as input. 但请确保您的方法接受接口而不是抽象类作为输入。

Coding against interfaces makes your design more flexible and extensible. 对接口进行编码使您的设计更加灵活和可扩展。 For instance, plugin frameworks and dependency injection. 例如,插件框架和依赖注入。 Without interfaces, the extensibility of it is pretty much limited. 没有接口,它的可扩展性非常有限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM