接口是否应该扩展其他接口(并以此继承方法)


13

尽管这是一个普遍的问题,但它也特定于我当前遇到的问题。我目前在解决方案中指定了一个接口,称为

public interface IContextProvider
{
   IDataContext { get; set; }
   IAreaContext { get; set; }
}

该接口经常在整个程序中使用,因此我可以轻松访问所需的对象。但是,在程序一部分的较低级别,我需要访问另一个将使用IAreaContext并对其执行一些操作的类。因此,我创建了另一个工厂接口来执行此创建操作:

public interface IEventContextFactory 
{
   IEventContext CreateEventContext(int eventId);
}

我有一个实现IContextProvider的类,并使用NinJect注入。我遇到的问题是,我需要使用此IEventContextFactory的区域只能访问IContextProvider,并且本身使用另一个需要该新接口的类。我不想在低级实例化IEventContextFactory的此实现,而是希望始终使用IEventContextFactory接口。但是我也不想只通过构造函数注入另一个参数,而只是将其传递给需要它的类,即

// example of problem
public class MyClass
{
    public MyClass(IContextProvider context, IEventContextFactory event)
    {
       _context = context;
       _event = event;
    }

    public void DoSomething() 
    {
       // the only place _event is used in the class is to pass it through
       var myClass = new MyChildClass(_event);
       myClass.PerformCalculation();      
    }
}

所以我的主要问题是,做这样的事情(接口扩展另一个接口)是否可以接受?

public interface IContextProvider : IEventContextFactory

或者我应该考虑实现我所需要的更好的替代方法。如果我没有提供足够的信息来提出建议,请告诉我,我可以提供更多。


2
我将您的问题标题改写为“应该接口继承接口”,因为没有接口实际实现任何东西。
Jesse C. Slicer 2012年

2
通常的语言是接口“扩展”其父接口,并且(这样做)“继承”父接口的方法,因此,我建议在这里使用“ extend”。
西奥多·默多克

接口可以扩展父级,那么为什么这是不好的做法?如果一个接口合法地是另一个接口的超集,则当然应该对其进行扩展。
罗宾·温斯洛

Answers:


10

尽管接口仅描述行为而没有任何实现,但它们仍可以参与继承层次结构。举例来说,假设您有一个共同的想法Collection。该接口将提供所有集合所共有的一些东西,例如一种遍历成员的方法。然后,您可以考虑一些更具体的对象集合,例如a List或a Set。这些中的每一个都继承了的所有行为要求Collection,但添加了特定于该特定类型的集合的其他要求。

只要有必要为接口创建继承层次结构,那么就应该这样做。如果将始终找到两个接口,则应该将它们合并。


6

是的,但前提是有意义。问自己以下问题,如果一个或多个适用,则可以从另一个继承接口。

  1. 接口A是否在逻辑上扩展了接口B,例如IList向ICollection添加功能。
  2. 接口A是否需要定义另一个接口已经指定的行为,例如,如果ID A具有需要整理的资源,则实现IDisposable;如果可以对其进行迭代,则实现IEnumerable。
  3. 接口A的每个实现都需要接口B指定的行为吗?

在您的示例中,我认为它不能回答任何一个问题。您最好将其添加为另一个属性:

public interface IContextProvider
{
   IDataContext DataContext { get; set; }
   IAreaContext AreaContext { get; set; }
   IEventContextFactory EventContextFactory { get; set; }
}

与扩展接口相比,使其具有更好的属性是什么,或者可以说是对猫进行蒙皮的另一种方式?
dreza 2012年

1
区别在于,如果您执行IContextProviderextend IEventContextFactory,则ContextProvider实现也将需要实现该方法。如果将其添加为属性,则表示a ContextProvider具有,IEventContextFactory但实际上并不知道实现细节。
Trevor Pilley 2012年

4

是的,可以从一个接口扩展另一个接口。

在特定情况下是否做对的问题取决于两者之间是否存在真正的“是”关系。

有效的“是”关系需要什么?

首先,两个接口之间必须有真正的区别,即必须存在实现父接口而不是子接口的实例。如果不存在并且永远不会存在不实现这两个接口的实例,则应该将这两个接口合并。

第二,必须是子接口的每个实例必须一定是父接口的实例的情况:没有(合理的)逻辑可以创建子接口的实例,而该逻辑对于父接口。

如果这两个都是正确的,那么继承是两个接口的正确关系。


我认为没有必要仅使用基本接口而不使用派生接口的类。例如,IReadOnlyList即使我所有的列表类都实现了IList(从派生IReadOnlyList),该接口也可能有用。
svick 2012年

1

如果一个接口总是想要/提供另一个接口,请继续。在某些情况下,我已经知道了这IDisposible一点。通常,您应该确保至少一个接口的行为更像是特性而不是职责。

对于您的示例,尚不清楚。如果它们总是在一起,则只需建立一个接口即可。如果一个人总是需要另一个,那么我会担心“ X和1”这种继承,这种继承通常会导致多重责任和/或其他渗漏的抽象问题。


感谢那。你的行为更像是一种特质而不是一种责任?
dreza 2012年

@dreza我的意思是像SOLID中的SRP一样负责,并且具有类似Scala特征之类的特征。主要是界面如何建模问题的概念。它代表问题的主要部分,还是代表其他类型完全不同的常见类型?
Telastyn 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.