使用C#接口,同时最大化代码重用

时间:2012-07-14 00:53:42

标签: c# inheritance interface solid-principles

所以说我有一个C#类,

class Foo : Bar, IBar, IBar2
{

}

...其中Bar是一个类,IWhatever和IFine是接口。我打算在多个类中使用类似的IWhatever和IFine实现 - 我可以看到封装这些代码并在所有类中重用它的唯一理智方法是创建一个类,无论继承自IW和I的继承自IFine和使它们成为实现这些接口的类的成员,然后在从接口实现的成员中调用它们的成员,如下所示:

class Foo : Bar, IWhatever, IFine
{
   IWhatever mWhatever;
   IFine mFine;
   Foo()
   {
      mWhatever = new Whatever();
      mFine = new Fine();
   }
   // from IWhatever
   void Kick()
   {
      mWhatever.Kick();
   }
   // from IFine
   void Punch()
   {
      mFine.Punch();
   }
}

我做得对吗?还有更好的方法吗?

3 个答案:

答案 0 :(得分:9)

当您尝试通过继承在多个类中实现相同的多个实现时,这是一种设计气味。 C#缺乏多重(类)继承实际上是一种资产,而不是这方面的责任,因为它强制执行单一责任原则。

以这种方式思考:C#中提供的两种类型的抽象有两种互补形式来表示现实生活实体。

  • 抽象类:“是一个”
  • 界面:“做某事”或“有这样的品质/行为”

这意味着接口应该几乎总是“空洞的”,因为我们假设即使不同的类可能实现相同的接口,很可能每个接口都会以不同的方式执行。

小心使用继承。记住GOF的圣人智慧:

  

赞成对象组合优于继承。

因此,回到你试图解决的问题,最好这样做:

public class Foo : Bar
{
   public IWhatever Whatever
   {
      get;
      private set;
   }

   public IFine Fine
   {
      get;
      private set;
   }

   public Foo(IWhatever whatever, IFine fine)
   {
      Whatever = whatever;
      Fine = fine;
   }
}

现在使用IOC容器注入这些接口的具体实现。这是我谦虚的建议。

答案 1 :(得分:3)

你可以使它更通用:

class Foo<TWhat, TFine> : Bar, IWhatever, IFine
    where TWhat : IWhatever, new()
    where TFine : IFine, new()
{
   IWhatever mWhatever;
   IFine mFine;
   Foo()
   {
      mWhatever = new TWhat();
      mFine = new TFine();
   }
   // from IWhatever
   public void Kick()
   {
      mWhatever.Kick();
   }
   // from IFine
   public void Punch()
   {
      mFine.Punch();
   }
}

这样,Foo可以使用任何实现IWhateverIFine的类,而不仅仅是WhateverFine

但是你是否愿意这样做取决于你。在我对代码的正确结构有什么看法之前,我需要更多具体的信息。

答案 2 :(得分:0)

您可以将接口更改为mixin-like,将成员作为扩展方法公开给接口:

interface MBar {} static class BarMethods {
  public static void M(this MBar self) { ... }
}

class Foo : MBar { ... }

整个构造interface MBar {} static class BarMethods { ... }可以被视为单个“模块”,如module MBar { ... }。这就是我保持格式化的原因。