2010-01-29 73 views
4

Heyho,为什么任何一种抽象都使用接口而不是抽象类?

现在在我的脑海一段时间

看到一只问题,其希望可以通过一些你快速清除:

我MVC的大风扇,ASP.Net的mvc在我的情况。

我注意到的是关于接口的宣传。每个视频,教程和书籍似乎都可以解决任何与接口有关的抽象问题。我已经适应了这些模式,了解为什么和如何,我基本上对它很满意。

但我只是不明白为什么接口在任何地方都被使用。我几乎从来没有看到抽象的基础类抽象化,我不明白。也许我想念什么?我知道你只能从一个基类继承而有多个接口。但是接口确实有缺点,特别是当需要做一些改变时,这会破坏你的实现。 在我迄今为止的项目中,我只用来为完全不同的类选择接口。

例如,整个存储库模式可以用抽象基类来完成,仍然提供可测试性和可交换性,或者我错过了什么?

请点我在我的大脑laggs :)

+2

title make brain aplode – Anonymous 2010-01-29 12:28:56

+0

我很伤心:) – Steffen 2010-01-29 14:45:21

+0

一般来说,你希望**组合**继承。 – 2010-01-29 16:16:53

回答

6

接口是在教程,博客中使用和部分其他地方,因为这些作家特别由一组方法称为“可测性设计”的影响。

首先,可测试性设计思想学派使用接口的每一个方式,因为他们希望能够模拟任何被测试的组件。如果你使用具体的类,那么许多嘲笑工具不能嘲笑这些类,因此将难以测试你的代码。

+3

+1以抵消没有根据的downvote。是的,您仍然可以测试何时使用抽象类,但通过嘲讽**的可测试性**是编程接口的合法和常见原因。 – Jay 2010-01-29 12:19:08

+0

允许使用Moq等工具进行嘲弄是一个很好的理由。 – 2010-01-29 12:28:25

+0

是的,我甚至使用Moq,并没有想到目前为止。有效点 – Steffen 2010-01-29 14:47:00

0

针对接口进行编码使您的设计更加灵活和可扩展。例如,插件框架和依赖注入。没有接口,它的可扩展性非常有限。

2

如果语言不支持多重继承或混合调用抽象基类与接口相比在范围上受到限制。例如。在.NET中,如果您必须继承其他类型(如MarshalByRef),则不能使用抽象基类来实现模式。接口不强加此限制。

1

除了你提到的只能从一个基类继承的事实(如果你想使用一个现有的类已经从一些新的框架基类继承而来,这很不方便),你也可以避免如果您使用接口,请改为fragile base class问题。

3

A Story

有一次我参加了一个Java用户组 会议,其中詹姆斯·高斯林(Java的发明者 )是主要发言人。 在难忘的Q & A session, 有人问他:“如果你可以再做 Java,你会 更改?” “我会放弃课程,”他回答说,他 。在笑声平息之后,他解释说 真实问题不是类本身,而是 实现继承( 扩展关系)。接口 继承(实现 关系)是优选的。您尽可能避免执行 继承。

虽然仅使用或主要使用Interfaces确实存在代码重用问题(以及消除很好的基类),它使得像继承类似的事情变得更容易。除了具有广泛不同的实现方式以外,它们还可以工作,并且不必担心基类会发生变化,甚至不需要担心它会发生什么(您必须实现整个事情,尽管它是一种折衷)。

P.S.我认为新的Go语言基于接口而不是继承(看起来很有趣)。

+0

您必须实现整个目标,是的,但是在需要继承的情况下,当然,您可以在基类中实现接口,然后继承,这样您就可以在不使用接口的情况下使用接口不得不重新实现每个类中通过继承在逻辑上相关的所有成员。 – Jay 2010-01-29 13:25:18

+0

话虽如此,VB4-6就是一个很好的例子,说明当这种类型的概念被严重实施时会发生什么。 COM确实支持接口继承,但缺乏实现继承(因此没有适当的框架支持)确实导致了VB6应用程序中的许多样板代码> -p – ConcernedOfTunbridgeWells 2010-01-29 13:36:58

+1

我的一个主要希望列表项是让接口指定默认实现或某些或所有成员,这样实施者只需实施与默认不同的成员。默认成员可以自己完成界面提供的动作,但是像IEnumerable 这样的东西可以例如提供一个默认的'Count()'方法,它将调用'GetEnumerator()'并计算枚举器返回的项目数。可以更有效地返回计数的实现可以用合适的东西覆盖该方法。 – supercat 2012-08-06 15:46:12

1

阅读关于接口,抽象类,突破性变化和MVC:http://ayende.com/Blog/archive/2008/02/21/Re-Versioning-Issues-With-Abstract-Base-Classes-and-Interfaces.aspx

在那里展示的一个解决方案(或Ayende博客上的某个地方else)是:使用接口,但也提供抽象类。那些关于突破变化的人可以将他们的实现建立在抽象类上。那些需要接口供电的人也很满意。但确保你的方法接受接口而不是抽象类作为输入。