在设计C#类库时,什么时候应该选择继承而不是接口?[英] When should I choose inheritance over an interface when designing C# class libraries?

本文是小编为大家收集整理的关于在设计C#类库时,什么时候应该选择继承而不是接口?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个数字Processor类,可以做两个截然不同的事情,但从普通代码中称为"控制"情况.

我想知道我应该在确定他们是否应全部从BaseProcessor中继承或实现IProcessor作为接口时,我应该认识哪些设计注意事项.

.

推荐答案

通常,规则是这样的:

  • 继承描述了 is-a 关系.
  • 实现界面描述 can-do-do 关系.

要以更具体的术语将其放置,让我们看一个示例. System.Drawing.Bitmap System.Drawing.Bitmap class is-is-as-an 图像(因此,它从Image类继承),但它也 can-do 处置,因此它实现了 IDisposable 接口.它还 can-do 序列化,因此它从 ISerializable 接口.

但更实际,接口通常用于模拟C#中的多个继承.如果您的Processor类需要从System.ComponentModel.Component之类的东西继承,那么您别无选择,只能实现IProcessor接口.

事实是,接口和抽象基类都提供了一份合同,指定特定类可以做什么.这是一个普遍的神话,即宣布该合同的界面是必要的,但这是不正确的.我脑海中最大的优点是,抽象基类允许您为子类提供默认功能.但是,如果没有有意义的默认功能,那么没有什么使您无法将方法本身标记为abstract,要求派生的类实现它,就像他们要实现界面一样.

.

对于此类问题的答案,我经常转到 .

通常,类是揭示抽象的首选构造.

接口的主要缺点是,在允许API的演变方面,它们的灵活性要比类要少得多.一旦您运送界面,其成员的集合将永远固定.接口的任何添加都会破坏实现接口的现有类型.

课程提供更大的灵活性.您可以将成员添加到已经发货的课程中.只要该方法不是抽象的(即,只要您提供该方法的默认实现),任何现有的派生类都会继续不变.

[. . . ]

有利于接口的最常见论点之一是,它们允许将合同与实施分开.但是,该参数错误地假设您不能使用类别将合同与实施分开.驻留在其具体实现的单独组装中的抽象类是实现这种分离的好方法.

他们的一般建议如下:

  • 做偏爱定义类而不是接口.
  • do 使用抽象类而不是接口将合同与实施中解除.摘要类,如果正确定义,则允许合同和实施之间的相同程度的解耦.
  • do 如果需要提供价值类型的多态性层次结构,则定义接口.
  • 考虑定义界面以实现与多重继承相似的效果.

克里斯·安德森(Chris Anderson)与最后的宗旨表达了特别的共识,认为:

抽象类型的版本要好得多,并允许将来的可扩展性,但它们也燃烧了您的唯一基本类型.当您真正定义两个随着时间的不变的对象之间的合同时,接口是合适的.抽象基础类型更好地定义类型家庭的共同基础.

其他推荐答案

Richard,

为什么选择它们?我将有一个IPROOCESER界面作为发布的类型(用于系统中的其他地方);而且,如果碰巧的是,您当前的各种实现IPROCESSOR具有共同的行为,那么抽象的基础处理器类将是实施该共同行为的真正好地方.

这样,如果您将来需要一个IPROCESSOR,而这不是基础处理器的服务,那么它不必拥有它(并可能隐藏它)...但是那些想要它的人可以拥有它. .削减重复的代码/概念.

只是我的拙见.

欢呼.基思.

其他推荐答案

接口是"合同",它们确保某些类实现一组所需的成员 - 属性,方法和事件 - .

基础类(具体或抽象,无关紧要)是某些实体的原型.那就是这些实体代表某些实际的物理或概念上常见的实体.

什么时候使用接口?

每当某种类型需要声明至少具有某些行为和属性时,消费者应该关心并使用它们来完成某些任务.

何时使用基类(具体和/或摘要)

每当一组实体共享相同的原型时,b继承a,因为b是A差异,但是B可以识别为A.


示例:

让我们谈谈桌子.

  • 我们接受可回收表 => 必须使用诸如" irecyclabletable"之类的接口来定义,以确保所有可回收表都将具有"回收"方法.

  • 我们想要桌面表 => 这必须通过继承来定义. "桌面表"是"表".所有表都有常见的属性和行为和桌面的属性.

我可以在对象图中谈论两种情况的含义,但是在我的意见中,如果我需要以概念的角度提出论据,我会用这种论点来回答.

本文地址:https://www.itbaoku.cn/post/627613.html

问题描述

I have a number Processor classes that will do two very different things, but are called from common code (an "inversion of control" situation).

I'm wondering what design considerations I should be cognicent (or cognizant, for you USsers) of when deciding if they should all inherit from BaseProcessor, or implement IProcessor as an interface.

推荐答案

Generally, the rule goes something like this:

  • Inheritance describes an is-a relationship.
  • 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.

其他推荐答案

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.

其他推荐答案

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.