Implementing an interface describes a can-do relationship.
To put this in somewhat more concrete terms, let's look at an example. The System.Drawing.Bitmap class is-an image (and as such, it inherits from the Image class), but it also can-do disposing, so it implements the IDisposable interface. It also can-do serialization, so it implements from the ISerializable interface.
But more practically, interfaces are often used to simulate multiple inheritance in C#. If your Processor class needs to inherit from something like System.ComponentModel.Component, then you have little choice but to implement an IProcessor interface.
The fact is that both interfaces and abstract base class provide a contract specifying what a particular class can do. It's a common myth that interfaces are necessary to declare this contract, but that's not correct. The biggest advantage to my mind is that abstract base classes allow you provide default functionality for the subclasses. But if there is no default functionality that makes sense, there's nothing keeping you from marking the method itself as abstract, requiring that derived classes implement it themselves, just like if they were to implement an interface.
For answers to questions like this, I often turn to the .NET Framework Design Guidelines, which have this to say about choosing between classes and interfaces:
In general, classes are the preferred construct for exposing abstractions.
The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for the evolution of APIs. Once you ship an interface, the set of its members is fixed forever. Any additions to the interface would break existing types implementing the interface.
A class offers much more flexibility. You can add members to classes that you have already shipped. As long as the method is not abstract (i.e., as long as you provide a default implementation of the method), any existing derived classes continue to function unchanged.
[ . . . ]
One of the most common arguments in favor of interfaces is that they allow separating contract from the implementation. However, the argument incorrectly assumes that you cannot separate contracts from implementation using classes. Abstract classes residing in a separate assembly from their concrete implementations are a great way to achieve such separation.
Their general recommendations are as follows:
Do favor defining classes over interfaces.
Do use abstract classes instead of interfaces to decouple the contract from implementations. Abstract classes, if defined correctly, allow for the same degree of decoupling between contract and implementation.
Do define an interface if you need to provide a polymorphic hierarchy of value types.
Consider defining interfaces to achieve a similar effect to that of multiple inheritance.
Chris Anderson expresses particular agreement with this last tenet, arguing that:
Abstract types do version much better, and allow for future extensibility, but they also burn your one and only base type. Interfaces are appropriate when you are really defining a contract between two objects that is invariant over time. Abstract base types are better for defining a common base for a family of types.
Why CHOOSE between them? I'd have an IProcessor interface as the published type (for use elsewhere in the system); and if it so happens that your various CURRENT implementations of IProcessor have common-behaviour, then an abstract BaseProcessor class would be a real good place to implement that common behaviour.
This way, if you require an IProcessor in future which does NOT have been for BaseProcessor's services, it doesn't HAVE to have it (and possibly hide it)... but those that do want it can have it... cutting down in duplicated code/concepts.
Interfaces are a "contract", these are ensuring some class implements a desired set of members - properties, methods and events -.
Base classes (concrete or abstract, doesn't matter) are the archetype of some entity. That's these are entities representing what's common in some actual physical or conceptual one.
When to use interfaces?
Whenever some type needs to declare that, at least, has some behaviors and properties that a consumer should care about and use them to accomplish some task.
When to use base classes (concrete and/or abstract)
Whenever a group of entities share same archetype, meaning B inherits A because B is A with differences, but B can be identified as A.
Examples:
Let's talk about tables.
We accept recyclable tables => This must be defined with an interface like "IRecyclableTable" ensuring that all recyclable tables are going to have a "Recycle" method.
We want desktop tables => This must be defined with inheritance. A "desktop table" is a "table". All tables have common properties and behaviors and desktop ones will have same ones adding such things that make a desktop table work different than other types of tables.
I could talk about associations, meaning of both cases in an object graph, but in my humild opinion, if I need to give arguments in a conceptual point of view, I would exactly answer with this argumentation.
I am not pretty good at design choices, but if asked, I will prefer implementing an iProcessor interface if there are only members to be extended. If there are other functions which need not to be extended, inheriting from baseprocessor is better option.
Given that the SOLID principles offer more maintainability and extensibility to your project, I'd prefer interfaces over inheritance.
Also, if you need to add "additional functionality" to your interface, best option is to create a new interface altogether, following the I in SOLID, which is Interface Seggregation Principle.
If whatever you choose don't matter, always choose Interface. It allows more flexibility. It might protect you from future changes (if you need to change something in the base class, the inherited classes might be affected). It also allow to encapsulate the details better. If you are using some Inversion of Control of Dependency Injection, they tend to favor interface.
Or if inheritance can't be avoided, probably a good idea to use both of them together. Create an abstract base class that implements an interface. In your case, ProcessorBase implements an IProcessor.
Similar to ControllerBase and IController in ASP.NET Mvc.
发布评论
评论(7)
一般来说,规则是这样的:
为了更具体地表达这一点,让我们看一个例子。
System.Drawing.Bitmap
class is-an image(因此,它继承自Image
类),但它也can-do 处理,所以它实现了IDisposable
接口。它还可以序列化,因此它从ISerialized
接口。但更实际的是,C# 中经常使用接口来模拟多重继承。如果您的 Processor 类需要从 System.ComponentModel.Component 之类的类继承,那么您别无选择,只能实现 IProcessor 接口。
事实上,接口和抽象基类都提供了一个约定,指定特定类可以做什么。人们普遍认为接口是声明此契约所必需的,但这是不正确的。我认为最大的优点是抽象基类允许您为子类提供默认功能。但是,如果没有有意义的默认功能,则没有什么可以阻止您将方法本身标记为抽象,要求派生类自己实现它,就像它们要实现接口一样。
对于此类问题的答案,我经常查阅 .NET Framework 设计指南 ,其中关于类和接口之间的选择有这样的说法:
他们的一般建议如下:
克里斯·安德森 (Chris Anderson) 对最后一个原则表示特别同意,他认为:
Generally, the rule goes something like this:
To put this in somewhat more concrete terms, let's look at an example. The
System.Drawing.Bitmap
class is-an image (and as such, it inherits from theImage
class), but it also can-do disposing, so it implements theIDisposable
interface. It also can-do serialization, so it implements from theISerializable
interface.But more practically, interfaces are often used to simulate multiple inheritance in C#. If your
Processor
class needs to inherit from something likeSystem.ComponentModel.Component
, then you have little choice but to implement anIProcessor
interface.The fact is that both interfaces and abstract base class provide a contract specifying what a particular class can do. It's a common myth that interfaces are necessary to declare this contract, but that's not correct. The biggest advantage to my mind is that abstract base classes allow you provide default functionality for the subclasses. But if there is no default functionality that makes sense, there's nothing keeping you from marking the method itself as
abstract
, requiring that derived classes implement it themselves, just like if they were to implement an interface.For answers to questions like this, I often turn to the .NET Framework Design Guidelines, which have this to say about choosing between classes and interfaces:
Their general recommendations are as follows:
Chris Anderson expresses particular agreement with this last tenet, arguing that:
理查德,
为什么要在他们之间做出选择?我有一个 IProcessor 接口作为 published 类型(用于系统中的其他地方);如果碰巧您当前的各种 IProcessor 实现具有共同行为,那么抽象 BaseProcessor 类将是实现该共同行为的真正好地方。
这样,如果您将来需要一个不用于 BaseProcessor 服务的 IProcessor,则不必拥有它(并且可能隐藏它)...但是那些确实想要它的人可以拥有它...在重复的代码/概念中。
只是我的拙见。
干杯。基思.
Richard,
Why CHOOSE between them? I'd have an IProcessor interface as the published type (for use elsewhere in the system); and if it so happens that your various CURRENT implementations of IProcessor have common-behaviour, then an abstract BaseProcessor class would be a real good place to implement that common behaviour.
This way, if you require an IProcessor in future which does NOT have been for BaseProcessor's services, it doesn't HAVE to have it (and possibly hide it)... but those that do want it can have it... cutting down in duplicated code/concepts.
Just my humble OPINION.
Cheers. Keith.
接口是一个“契约”,它们确保某个类实现一组所需的成员 - 属性、方法和事件 -。
基类(具体的或抽象的,并不重要)是某些实体的原型。这些实体代表了某些实际物理或概念实体中的常见内容。
何时使用接口?
每当某种类型需要声明时,至少具有消费者应该关心的一些行为和属性,并使用它们来完成某些任务。
< strong>何时使用基类(具体和/或抽象)
每当一组实体共享相同的原型时,这意味着 B 继承 A,因为 B 是有差异的 A,但 B 可以被识别为 A。< /em>
示例:
让我们来谈谈桌子。
我们接受可回收的桌子 => 这必须使用“IRecyclableTable”之类的接口进行定义,确保所有可回收表都将具有“Recycle”方法。
我们想要桌面桌 => 这必须通过继承来定义。 “桌面桌”就是“桌子”。所有表格都有共同的属性和行为,桌面表格将具有相同的属性和行为,添加一些使桌面表格的工作方式与其他类型的表格不同的内容。
我可以谈论关联,即对象图中两种情况的含义,但是以我拙见,如果我需要从概念的角度进行论证,我会准确地回答这个论证。
Interfaces are a "contract", these are ensuring some class implements a desired set of members - properties, methods and events -.
Base classes (concrete or abstract, doesn't matter) are the archetype of some entity. That's these are entities representing what's common in some actual physical or conceptual one.
When to use interfaces?
Whenever some type needs to declare that, at least, has some behaviors and properties that a consumer should care about and use them to accomplish some task.
When to use base classes (concrete and/or abstract)
Whenever a group of entities share same archetype, meaning B inherits A because B is A with differences, but B can be identified as A.
Examples:
Let's talk about tables.
We accept recyclable tables => This must be defined with an interface like "IRecyclableTable" ensuring that all recyclable tables are going to have a "Recycle" method.
We want desktop tables => This must be defined with inheritance. A "desktop table" is a "table". All tables have common properties and behaviors and desktop ones will have same ones adding such things that make a desktop table work different than other types of tables.
I could talk about associations, meaning of both cases in an object graph, but in my humild opinion, if I need to give arguments in a conceptual point of view, I would exactly answer with this argumentation.
我不太擅长设计选择,但如果被问到,如果只有成员需要扩展,我会更喜欢实现 iProcessor 接口。如果还有其他不需要扩展的功能,继承baseprocessor是更好的选择。
I am not pretty good at design choices, but if asked, I will prefer implementing an iProcessor interface if there are only members to be extended. If there are other functions which need not to be extended, inheriting from baseprocessor is better option.
撇开设计的纯粹性不谈,你只能继承一次,所以,如果你需要继承一些框架类,这个问题就没有实际意义了。
如果您有选择,实际上您可以选择节省最多打字时间的选项。无论如何,它通常是最纯粹的选择。
编辑:
如果基类有一些实现,那么这可能很有用,如果它纯粹是抽象的,那么它也可能是一个接口。
Design purity aside, you can inherit only once so, if you need to inherit some framework class the question is moot.
If you have a choice, pragmatically you can choose the option that saves the most typing. Its usually the purist choice anyway.
EDIT:
If the base class will have some implementation then this could be useful, if it is purely abstact then it may as well be an interface.
鉴于 SOLID 原则为您的项目提供了更多的可维护性和可扩展性,我更喜欢接口而不是继承。
另外,如果您需要向界面添加“附加功能”,最好的选择是完全创建一个新界面,遵循 SOLID 中的 I,即界面隔离原则。
Given that the SOLID principles offer more maintainability and extensibility to your project, I'd prefer interfaces over inheritance.
Also, if you need to add "additional functionality" to your interface, best option is to create a new interface altogether, following the I in SOLID, which is Interface Seggregation Principle.
如果您选择的任何内容都不重要,请始终选择“接口”。它允许更大的灵活性。它可能会保护您免受未来更改的影响(如果您需要更改基类中的某些内容,继承的类可能会受到影响)。它还可以更好地封装细节。如果您正在使用某些依赖注入控制反转,它们往往会偏向于接口。
或者,如果继承无法避免,那么将它们一起使用可能是个好主意。创建一个实现接口的抽象基类。在您的例子中,ProcessorBase 实现了一个 IProcessor。
类似于 ASP.NET Mvc 中的 ControllerBase 和 IController。
If whatever you choose don't matter, always choose Interface. It allows more flexibility. It might protect you from future changes (if you need to change something in the base class, the inherited classes might be affected). It also allow to encapsulate the details better. If you are using some Inversion of Control of Dependency Injection, they tend to favor interface.
Or if inheritance can't be avoided, probably a good idea to use both of them together. Create an abstract base class that implements an interface. In your case, ProcessorBase implements an IProcessor.
Similar to ControllerBase and IController in ASP.NET Mvc.