由于多重继承是不好的(它使源代码更加复杂),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的所有方法,所以将这两个方法合并到一个类中是最简单的解决方案。

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


当前回答

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.

其他回答

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

如果X继承了Y,这有两个正交的效果:

Y将为X提供默认功能,因此X的代码只需要包含与Y不同的东西。 几乎在任何需要用Y的地方,都可以用X代替。

Although inheritance provides for both features, it is not hard to imagine circumstances where either could be of use without the other. No .net language I know of has a direct way of implementing the first without the second, though one could obtain such functionality by defining a base class which is never used directly, and having one or more classes that inherit directly from it without adding anything new (such classes could share all their code, but would not be substitutable for each other). Any CLR-compliant language, however, will allow the use of interfaces which provide the second feature of interfaces (substitutability) without the first (member reuse).

由于多重继承(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();
    }
}

在我自己的实现中,我发现在MI中使用类/接口,虽然“形式很好”,但往往过于复杂,因为你需要为几个必要的函数调用设置所有的多重继承,在我的例子中,需要做几十倍的冗余。

相反,简单地在不同的模块化变体中创建静态的“调用调用函数的函数”作为一种面向对象的替代会更容易。我所致力于的解决方案是RPG的“法术系统”,即在不需要重新编写代码的情况下,效果需要大量混合和匹配函数调用来提供各种各样的法术,就像这个例子所表明的那样。

大多数函数现在都可以是静态的,因为我不必为拼写逻辑需要实例,而类继承在静态时甚至不能使用虚拟或抽象关键字。接口根本不能使用它们。

在我看来,这样编码更快更干净。如果只是使用函数,并且不需要继承属性,则使用函数。