什么时候应该在deviseC#类库时通过接口selectinheritance?
我有一个Processor
类,将做两个完全不同的事情,但从通用代码(“控制反转”情况)调用。
我想知道什么样的devise考虑因素,在决定它们是否应该全部从BaseProcessor
inheritance,或者实现IP Processor作为接口时,我应该认识到(或认识到,对于你的USsers)。
一般来说,规则是这样的:
- inheritance描述的是一种关系。
- 实现一个接口描述了一个可以做的关系。
为了更具体一些,我们来看一个例子。 System.Drawing.Bitmap
类是一个图像(因此它inheritance自Image
类),但它也可以进行configuration ,所以它实现了IDisposable
接口。 它也可以做序列化,所以它从ISerializable
接口实现。
但更实际的是,接口常常被用来模拟C#中的多重inheritance。 如果Processor
类需要inheritanceSystem.ComponentModel.Component
类的东西,那么除了实现一个IP Processor
接口外,别无select。
事实是,接口和抽象基类都提供了一个指定特定类可以做什么的合约。 这是一个常见的神话,接口是必要的,以宣布这个合同,但这是不正确的。 我认为最大的好处是抽象基类允许为子类提供默认function。 但是,如果没有默认的function是有意义的,那么就没有什么能够将方法本身标记为abstract
,要求派生类自己实现它,就好像它们要实现一个接口一样。
对于这样的问题的答案,我经常谈到.NET框架devise指南 ,这就是关于在类和接口之间进行select的说法。
一般来说,类是暴露抽象的首选构造。
接口的主要缺点是在允许API进化的时候,它们比类更不灵活。 一旦你发布了一个接口,它的成员集就永远是固定的。 对接口的任何添加都会破坏实现接口的现有types。
一个类提供更多的灵活性。 您可以将成员添加到已发送的类中。 只要方法不是抽象的(即,只要您提供方法的默认实现),任何现有的派生类将继续保持不变。
[。 。 。 ]
支持接口的最常见的观点之一就是它们允许从实现中分离契约。 但是,该参数错误地假定您不能使用类将实现与实现分开。 抽象类位于具体实现的独立程序集中,是实现这种分离的好方法。
他们的一般build议如下:
- 喜欢在接口上定义类。
- 不要使用抽象类而是使用接口来将契约与实现分离。 如果定义正确,抽象类允许合同和实现之间的相同程度的解耦。
- 如果您需要提供值types的多态层次结构,请定义一个接口。
- 考虑定义接口以实现与多重inheritance类似的效果。
克里斯·安德森表示特别同意这最后的信条,认为:
抽象types的版本要好得多,并且考虑到将来的扩展性,但是它们也会刻录你唯一的基本types。 当你真正定义两个不变的对象之间的契约时,接口是合适的。 抽象基types更适合为一族types定义公共基础。
理查德,
为什么select他们之间? 我有一个IP处理器接口作为发布的types(用于系统中的其他地方); 如果碰巧你的IP处理器的各种CURRENT实现有共同的行为,那么抽象的BaseProcessor类将是一个真正的实现这个共同行为的好地方。
这样,如果你将来需要一个IP处理器,而不是用于BaseProcessor的服务,那么它不需要拥有它(可能隐藏它),但是那些需要它的可以拥有它…减less在重复的代码/概念。
只是我谦虚的意见。
干杯。 基思。
接口是一个“契约”,它们确保某些类实现了所需的一组成员 – 属性,方法和事件。
基类(具体或抽象,无所谓)是某个实体的原型。 这就是这些实体,代表了一些实际的物理或概念的实体。
何时使用接口?
每当有些types需要声明,至less有一些消费者应该关心的行为和属性,并使用它们来完成某些任务。
何时使用基类(具体和/或抽象)
每当一组实体共享相同的原型时,意味着Binheritance了A,因为B是有区别的,但是B可以被认为是A.
例子:
我们来谈谈桌子。
-
我们接受可回收的表格 => 这必须用像“IRecyclableTable”这样的接口来定义,以确保所有的可回收表格都将具有“回收”方法 。
-
我们想要桌面表格 => 这个必须用inheritance来定义。 “桌面桌子”是一个“桌子”。 所有的表格都有共同的属性和行为,而桌面的表格会有相同的属性和行为,增加桌面表格的工作方式与其他types的表格不同。
我可以在一个对象图中谈论这两种情况的关联性,但是在我的模糊观点中,如果我需要从概念的angular度来提出论据,我会准确地回答这个论证。
我不擅长deviseselect,但如果被问到,如果只有成员被扩展,我更愿意实现一个iProcessor接口。 如果还有其他function不需要扩展,从基本处理器inheritance是更好的select。
除了devise纯度,你只能inheritance一次,如果你需要inheritance一些框架类的问题是没有意义的。
如果您有select,务实可以select保存最多input的选项。 无论如何,它通常是纯粹的select。
编辑:
如果基类有一些实现,那么这可能是有用的,如果它是纯粹的抽象,那么它可能是一个接口。
如果你select无关紧要,总是select接口。 它允许更多的灵活性。 它可以保护你免受未来的变化(如果你需要改变基类中的东西,inheritance的类可能会受到影响)。 它也允许更好地封装细节。 如果你正在使用一些dependency injection控制,他们倾向于接口。
或者,如果inheritance无法避免,那么把它们一起使用可能是一个好主意。 创build一个实现接口的抽象基类。 在你的情况下,ProcessorBase实现一个IP处理器。
与ASP.NET Mvc中的ControllerBase和IController类似。