3

所以说我有一个 C# 类,

class Foo : Bar, IBar, IBar2
{

}

... 其中 Bar 是一个类,而 IWhatever 和 Ifine 是接口。我计划在多个类中使用 IWhatever 和 IFine 的类似实现——我能看到封装此代码并在所有类中重用它的唯一明智的方法是创建一个继承自 IWhatever 和 Fine 的类继承自 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();
   }
}

我做对了吗?有没有更好的办法?

4

3 回答 3

9

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

可以这样想:C# 中可用的两种抽象类型有两种互补的形式来表示现实生活中的实体。

  • 抽象类:“Is a”
  • 界面:“做某事”或“有这样那样的品质/行为”

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

小心使用继承。记住 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 容器来注入这些接口的具体实现。这是我谦虚的建议。

于 2012-07-14T01:13:18.537 回答
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可以使用任何实现IWhateverand的类IFine,而不仅仅是Whateverand Fine

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

于 2012-07-14T01:03:34.740 回答
0

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

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

class Foo : MBar { ... }

整个结构interface MBar {} static class BarMethods { ... }可以看作是一个单一的“模块”,比如module MBar { ... }. 这就是为什么我保持这样的格式。

于 2012-07-14T01:17:49.963 回答