由于多重继承是不好的(它使源代码更加复杂),c#没有直接提供这样的模式。但有时候拥有这种能力是有帮助的。

例如,我能够使用接口和三个类实现缺少的多重继承模式:

public interface IFirst { void FirstMethod(); }
public interface ISecond { void SecondMethod(); }

public class First:IFirst 
{ 
    public void FirstMethod() { Console.WriteLine("First"); } 
}

public class Second:ISecond 
{ 
    public void SecondMethod() { Console.WriteLine("Second"); } 
}

public class FirstAndSecond: IFirst, ISecond
{
    First first = new First();
    Second second = new Second();
    public void FirstMethod() { first.FirstMethod(); }
    public void SecondMethod() { second.SecondMethod(); }
}

每当我向其中一个接口添加方法时,我也需要更改类FirstAndSecond。

是否有一种方法可以像在c++中那样将多个现有类注入到一个新类中?

也许有一种使用某种代码生成的解决方案?

或者它看起来像这样(虚构的c#语法):

public class FirstAndSecond: IFirst from First, ISecond from Second
{ }

这样,当我修改其中一个接口时,就不需要更新类FirstAndSecond。


EDIT

也许考虑一个实际的例子会更好:

您有一个现有的类(例如,基于ITextTcpClient的基于文本的TCP客户端),您已经在项目中的不同位置使用它。现在,您觉得有必要创建一个类的组件,以便windows窗体开发人员可以轻松访问。

据我所知,你目前有两种方法来做到这一点:

编写一个从组件继承的新类,并使用类本身的实例实现TextTcpClient类的接口,如FirstAndSecond所示。 编写一个继承TextTcpClient的新类,并以某种方式实现IComponent(实际上还没有尝试过这个)。

在这两种情况下,您都需要为每个方法而不是每个类做工作。因为你知道我们将需要TextTcpClient和Component的所有方法,所以将这两个方法合并到一个类中是最简单的解决方案。

为了避免冲突,这可以通过代码生成来完成,结果可以在之后修改,但手动输入这是一个纯粹的痛苦。


当前回答

我知道我知道 尽管这是不允许的,但有时候你确实需要它,比如:

class a {}
class b : a {}
class c : b {}

就我而言,我想这样做 class b: Form(对,就是windows.forms) 类c: b {}

因为有一半的函数是相同的,你必须重写它们

其他回答

您可以有一个实现IFirst和ISecond的抽象基类,然后从该基类继承。

我知道我知道 尽管这是不允许的,但有时候你确实需要它,比如:

class a {}
class b : a {}
class c : b {}

就我而言,我想这样做 class b: Form(对,就是windows.forms) 类c: b {}

因为有一半的函数是相同的,你必须重写它们

Multiple inheritance is one of those things that generally causes more problems than it solves. In C++ it fits the pattern of giving you enough rope to hang yourself, but Java and C# have chosen to go the safer route of not giving you the option. The biggest problem is what to do if you inherit multiple classes that have a method with the same signature that the inheritee doesn't implement. Which class's method should it choose? Or should that not compile? There is generally another way to implement most things that doesn't rely on multiple inheritance.

由于多重继承(MI)的问题时常出现,我想添加一种方法来解决组合模式的一些问题。

我建立在IFirst, ISecond,First, Second, firststandsecond方法的基础上,就像问题中提到的那样。我将示例代码减少到IFirst,因为无论接口/ MI基类的数量如何,模式都保持不变。

让我们假设,MI First和MI Second都派生自同一个基类BaseClass,只使用BaseClass中的公共接口元素

这可以通过在第一个和第二个实现中向BaseClass添加容器引用来表示:

class First : IFirst {
  private BaseClass ContainerInstance;
  First(BaseClass container) { ContainerInstance = container; }
  public void FirstMethod() { Console.WriteLine("First"); ContainerInstance.DoStuff(); } 
}
...

当引用BaseClass中受保护的接口元素时,或者当First和Second是MI中的抽象类时,要求它们的子类实现一些抽象部分,事情就变得更加复杂了。

class BaseClass {
  protected void DoStuff();
}

abstract class First : IFirst {
  public void FirstMethod() { DoStuff(); DoSubClassStuff(); }
  protected abstract void DoStuff(); // base class reference in MI
  protected abstract void DoSubClassStuff(); // sub class responsibility
}

c#允许嵌套类访问其包含类的受保护/私有元素,因此这可以用于链接来自第一个实现的抽象位。

class FirstAndSecond : BaseClass, IFirst, ISecond {
  // link interface
  private class PartFirst : First {
    private FirstAndSecond ContainerInstance;
    public PartFirst(FirstAndSecond container) {
      ContainerInstance = container;
    }
    // forwarded references to emulate access as it would be with MI
    protected override void DoStuff() { ContainerInstance.DoStuff(); }
    protected override void DoSubClassStuff() { ContainerInstance.DoSubClassStuff(); }
  }
  private IFirst partFirstInstance; // composition object
  public FirstMethod() { partFirstInstance.FirstMethod(); } // forwarded implementation
  public FirstAndSecond() {
    partFirstInstance = new PartFirst(this); // composition in constructor
  }
  // same stuff for Second
  //...
  // implementation of DoSubClassStuff
  private void DoSubClassStuff() { Console.WriteLine("Private method accessed"); }
}

这里涉及到相当多的样板文件,但是如果FirstMethod和SecondMethod的实际实现足够复杂,并且访问的私有/受保护方法的数量适中,那么这种模式可能有助于克服缺乏多重继承的问题。

考虑只使用组合而不是尝试模拟多重继承。你可以使用接口来定义组成组合的类,例如:isteable暗示了方向盘类型的属性,IBrakable暗示了BrakePedal类型的属性,等等。

一旦你完成了这些,你可以使用c# 3.0中添加的扩展方法功能来进一步简化对这些隐含属性的方法调用,例如:

public interface ISteerable { SteeringWheel wheel { get; set; } }

public interface IBrakable { BrakePedal brake { get; set; } }

public class Vehicle : ISteerable, IBrakable
{
    public SteeringWheel wheel { get; set; }

    public BrakePedal brake { get; set; }

    public Vehicle() { wheel = new SteeringWheel(); brake = new BrakePedal(); }
}

public static class SteeringExtensions
{
    public static void SteerLeft(this ISteerable vehicle)
    {
        vehicle.wheel.SteerLeft();
    }
}

public static class BrakeExtensions
{
    public static void Stop(this IBrakable vehicle)
    {
        vehicle.brake.ApplyUntilStop();
    }
}


public class Main
{
    Vehicle myCar = new Vehicle();

    public void main()
    {
        myCar.SteerLeft();
        myCar.Stop();
    }
}