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

我似乎找不到这个问题的答案,只是想确保它是一个 OK 的编码标准。我有接口 A,是由许多不同的类使用,并不希望接口 A的变化。我遇到了一个新的需求,它需要一个枚举来满足许多实现接口 A的类的需要,但并不是所有的类都需要这个枚举。我不希望那些不需要这个新枚举来实现这个新功能的类。因此,我创建了包含我需要添加的新枚举的接口 B。然后我让接口 B继承接口 A,这是我关心的问题,一个接口继承另一个接口可以吗?为了继续进行更改,我随后更改了需要新枚举来实现接口 B而不是接口 A的类,因为它是由接口 B继承的。我考虑过在我的类中实现需要它们的两个接口,但是我在整个代码中都使用这个接口,并且希望只使用一个接口来查看类,而不是使用两个接口。

我希望这是足够清楚的(可能太长) ,但如果任何人可以给我一些建议,无论是我做的正确或我做的错误,请让我知道。

谢谢!

75601 次浏览

Interface inheritance is an excellent tool, though you should only use it when interface B is truly substitutable for interface A, not just to aggregate loosely-related behaviors.

It's difficult to tell whether it is appropriate for your specific case, but there's nothing wrong using the practice in principle. You see it in the first-rate APIs all the time. To pick just one common example, from the .NET framework:

public interface ICollection<T> : IEnumerable<T>, IEnumerable

IMO this is exactly the right approach, I don't see any problem with it.

It is certainly possible to have an inheritance tree of interfaces, and even "multiple inheritance" with interfaces. Whether it is the right thing to do or not depends on the interfaces in question. If it really is the case that interface B is an extension or refinement of interface A, then inheritance makes sense, but if the new enum is largely unrelated to the concept expressed by interface A, I would make them two separate interfaces and have the classes that need to implement both interfaces.

Technically speaking, interfaces don't inherit from each other. What really happens when you create an IFoo that inherits from IBar, you're saying that any class that implements IFoo must also implement IBar.

interface IBar
{
void DoBar();
}


interface IFoo : IBar
{
void DoFoo();
}

In this example, the IFoo interface does not have a DoBar() method. Most of the time the distinction doesn't matter, but it can bite you when using reflection on an interface rather than a class.

I think databases always provide a great way to demonstrate interfaces, so considering if an interface should inherit another interface look at the following,

IMySqlDatabase : IDatabase
MySqlDatabase : IMySqlDatabase


IMsSqlDatabase : IDatabase
MsSqlDatabase : IMsSqlDatabase

A MySqlDatabase IS an IMySqlDatabase and an IMySqlDatabase IS an IDatabase.

Now if you need to make changes to your IDatabase interface it's grandchildren (the conrete database classes) can reap the benefits, but you won't have to expand MySQL AND MsSQL (or perhaps even more DBMS' Interfaces). At the same time in your middle man (IMsSqlDatabase) you can still have interface features that a MySQL or Oracle DB wouldn't support.

Consider whether the interfaces should be logically paired, and if you feel that they work well with each other then absolutely use inheritance.

Lets look at an example;

public interface IScanner
{
void Scan();
}


public interface IPrinter
{
void Print();
}

Printers and scanners are often separate objects, each with their own functionality however these two devices are often paired in the same device;

public interface IPhotocopier : IScanner, IPrinter
{
void Copy();
}

It makes sense that IPhotocopier should inherit from IScanner and IPrinter as this now allows the photocopier to be used as either a scanner or printer (which it contains) in addition to its primary roll as a copier.

Now lets look at one more interface;

public interface IBlender
{
void Blend();
}

It would not make sense to allow IBlender to be inherited by any of the earlier interfaces (what would you call them? IBlendingScanner?).

If you can't give your new interface a sensible name this might indicate that your may not want to use inheritance in this instance.

It's a bad idea to inherit some interfaces such as IDisposable, since this forces all implementations of your new interface to implement the dispose pattern even if they do not have any disposable resources.