一个接口是否应继承另一个接口

ajr*_*son 63 .net oop inheritance

我似乎无法找到答案,只是想确保它是一个好的编码标准.我有接口A,它被许多不同的类使用,并且不希望接口A发生变化.我遇到了一个新的需求,它要求许多实现接口A的类需要枚举,但并不是所有的类都需要这个枚举.我不希望不需要这个新枚举的类来实现这个新功能.所以我创建了包含我需要添加的新枚举的接口B. 然后我创建了接口B继承接口A,这是我关心的问题,一个接口是否可以继承另一个接口?为了继续我的更改,我然后将需要新枚举的类更改为实现接口B而不是接口A,因为它是由接口B继承的.我考虑在我的类中实现两个接口,但是我正在使用整个代码中的接口,并希望只使用一个接口来查看类,而不是两个.

我希望这很清楚(可能很长)但如果有人能给我一些建议,要么我做得对,要么我做错了请告诉我.

谢谢!

Jef*_*nal 71

接口继承是一个很好的工具,但是当接口B真正可替代接口A时,你应该只使用它,而不仅仅是聚合松散相关的行为.

很难说它是否适合您的具体案例,但原则上使用这种做法并没有错.您始终可以在一流的API中看到它.从.NET框架中选择一个常见示例:

public interface ICollection<T> : IEnumerable<T>, IEnumerable
Run Code Online (Sandbox Code Playgroud)

  • 我最初建议应适用Liskov替代原则.回想起来,这并不是真正相关的.LSP的大多数要求(维护不变量,对条件前和条件的限制)实际上只适用于具体实现,而不适用于接口.话虽如此,可替代性的一般原则仍应指导接口继承决策. (2认同)

mar*_*k_h 19

考虑接口是否应该在逻辑上配对,如果你觉得它们彼此配合良好,那么绝对使用继承.

让我们看一个例子;

public interface IScanner
{
    void Scan();
}

public interface IPrinter
{
    void Print();
}
Run Code Online (Sandbox Code Playgroud)

打印机和扫描仪通常是单独的对象,每个对象都有自己的功能,但这两个设备通常在同一设备中配对;

public interface IPhotocopier : IScanner, IPrinter
{
    void Copy();
}
Run Code Online (Sandbox Code Playgroud)

这是有道理的IPhotocopier应从所以IScanner和IPrinter继承这是因为现在允许复印机用作除了其主辊作为复印机或者扫描仪或打印机(它包含).

现在让我们再看一个界面;

public interface IBlender
{
    void Blend();
}
Run Code Online (Sandbox Code Playgroud)

允许IBlender被任何早期接口继承是没有意义的(你会称它们为什么?IBlendingScanner?).

如果您不能为新界面提供合理的名称,则可能表明您可能不希望在此实例中使用继承.

继承一些接口(如IDisposable)是一个坏主意,因为这会强制新接口的所有实现实现dispose模式,即使它们没有任何可支配资源.


Joe*_*ler 9

从技术上讲,接口不会相互继承.当你创建一个IFoo继承的时候会发生什么IBar,你说任何实现的类都IFoo必须实现IBar.

interface IBar
{
    void DoBar();
}

interface IFoo : IBar
{
    void DoFoo();
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,IFoo接口没有DoBar()方法.大多数情况下,这种区别并不重要,但是当在界面而不是类上使用反射时,它会咬你.

  • 即使考虑到你所描述的行为(在Phil Haack最近的专栏中详细描述,http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx),我认为它过于混乱了当C#参考文档甚至使用该术语时,说'接口不会在C#中继承',如"接口可以从一个或多个基接口继承".(http://msdn.microsoft.com/en-us/library/87d83y5b%28VS.80%29.aspx)我只想说,在C#中,当反映继承成员时,接口继承的行为与类继承不同. (5认同)

qid*_*qid 6

当然可以有一个接口的继承树,甚至是带接口的"多重继承".是否正确的做法取决于所讨论的接口.如果接口B的实际情况是接口A的扩展或细化,那么继承是有意义的,但如果新的枚举与接口A表达的概念基本无关,我会将它们作为两个独立的接口并具有类需要实现两个接口.


Des*_*tar 5

我认为数据库总是提供一种很好的方式来演示接口,因此考虑一个接口是否应该继承另一个接口,请看以下内容,

IMySqlDatabase : IDatabase
MySqlDatabase : IMySqlDatabase

IMsSqlDatabase : IDatabase
MsSqlDatabase : IMsSqlDatabase
Run Code Online (Sandbox Code Playgroud)

MySqlDatabase 是 IMySqlDatabase,IMySqlDatabase 是 IDatabase。

现在,如果您需要更改 IDatabase 接口,它的孙子(具体数据库类)可以从中受益,但您不必扩展 MySQL 和 MsSQL(或者甚至更多的 DBMS 接口)。同时,在中间人 (IMsSqlDatabase) 中,您仍然可以拥有 MySQL 或 Oracle DB 不支持的接口功能。