C#中的多重继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/178333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:45:22  来源:igfitidea点击:

Multiple Inheritance in C#

c#interfacemultiple-inheritance

提问by Martin

Since multiple inheritance is bad (it makes the source more complicated) C# does not provide such a pattern directly. But sometimes it would be helpful to have this ability.

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

For instance I'm able to implement the missing multiple inheritance pattern using interfaces and three classes like that:

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

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(); }
}

Every time I add a method to one of the interfaces I need to change the class FirstAndSecondas well.

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

Is there a way to inject multiple existing classes into one new class like it is possible in C++?

有没有办法像在 C++ 中那样将多个现有类注入一个新类?

Maybe there is a solution using some kind of code generation?

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

Or it may look like this (imaginary c# syntax):

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

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

So that there won't be a need to update the class FirstAndSecond when I modify one of the interfaces.

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



EDIT

编辑

Maybe it would be better to consider a practical example:

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

You have an existing class (e.g. a text based TCP client based on ITextTcpClient) which you do already use at different locations inside your project. Now you feel the need to create a component of your class to be easy accessible for windows forms developers.

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

As far as I know you currently have two ways to do this:

据我所知,您目前有两种方法可以做到这一点:

  1. Write a new class that is inherited from components and implements the interface of the TextTcpClient class using an instance of the class itself as shown with FirstAndSecond.

  2. Write a new class that inherits from TextTcpClient and somehow implements IComponent (haven't actually tried this yet).

  1. 编写一个从组件继承的新类,并使用类本身的实例实现 TextTcpClient 类的接口,如 FirstAndSecond 所示。

  2. 编写一个继承自 TextTcpClient 并以某种方式实现 IComponent 的新类(实际上还没有尝试过)。

In both cases you need to do work per method and not per class. Since you know that we will need all the methods of TextTcpClient and Component it would be the easiest solution to just combine those two into one class.

在这两种情况下,您都需要按方法而不是按类进行工作。由于您知道我们将需要 TextTcpClient 和 Component 的所有方法,因此将这两个方法合并为一个类将是最简单的解决方案。

To avoid conflicts this may be done by code generation where the result could be altered afterwards but typing this by hand is a pure pain in the ass.

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

采纳答案by IanNorton

Since multiple inheritance is bad (it makes the source more complicated) C# does not provide such a pattern directly. But sometimes it would be helpful to have this ability.

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

C# and the .net CLR have not implemented MI because they have not concluded how it would inter-operate between C#, VB.net and the other languages yet, not because "it would make source more complex"

C# 和 .net CLR 没有实现 MI,因为他们还没有总结出它如何在 C#、VB.net 和其他语言之间进行互操作,而不是因为“它会使源代码更加复杂”

MI is a useful concept, the un-answered questions are ones like:- "What do you do when you have multiple common base classes in the different superclasses?

MI 是一个有用的概念,未回答的问题是这样的:-“当您在不同的超类中有多个共同的基类时,您会怎么做?

Perl is the only language I've ever worked with where MI works and works well. .Net may well introduce it one day but not yet, the CLR does already support MI but as I've said, there are no language constructs for it beyond that yet.

Perl 是我曾经使用过的唯一一种 MI 工作并且工作良好的语言。.Net 可能有一天会推出它,但现在还没有,CLR 确实已经支持 MI,但正如我所说,除此之外还没有其他语言结构。

Until then you are stuck with Proxy objects and multiple Interfaces instead :(

在那之前,你会被代理对象和多个接口所困扰:(

回答by Joel Coehoorn

You could have one abstract base class that implements both IFirst and ISecond, and then inherit from just that base.

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

回答by Chris Wenham

Consider just using compositioninstead of trying to simulate Multiple Inheritance. You can use Interfaces to define what classes make up the composition, eg: ISteerableimplies a property of type SteeringWheel, IBrakableimplies a property of type BrakePedal, etc.

考虑只使用组合而不是尝试模拟多重继承。您可以使用接口来定义组成组合的类,例如:ISteerable隐含 type 属性SteeringWheelIBrakable隐含 type 属性BrakePedal等。

Once you've done that, you could use the Extension Methodsfeature added to C# 3.0 to further simplify calling methods on those implied properties, eg:

完成后,您可以使用添加到 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();
    }
}

回答by Amy B

If you can live with the restriction that the methods of IFirst and ISecond must only interact with the contract of IFirst and ISecond (like in your example)... you can do what you ask with extension methods. In practice, this is rarely the case.

如果您可以接受 IFirst 和 ISecond 的方法只能与 IFirst 和 ISecond 的合同交互的限制(如您的示例中所示)……您可以使用扩展方法执行您的要求。在实践中,这种情况很少发生。

public interface IFirst {}
public interface ISecond {}

public class FirstAndSecond : IFirst, ISecond
{
}

public static MultipleInheritenceExtensions
{
  public static void First(this IFirst theFirst)
  {
    Console.WriteLine("First");
  }

  public static void Second(this ISecond theSecond)
  {
    Console.WriteLine("Second");
  }
}

///

///

public void Test()
{
  FirstAndSecond fas = new FirstAndSecond();
  fas.First();
  fas.Second();
}

So the basic idea is that you define the required implementation in the interfaces... this required stuff should support the flexible implementation in the extension methods. Anytime you need to "add methods to the interface" instead you add an extension method.

所以基本思想是你在接口中定义所需的实现......这些必需的东西应该支持扩展方法中的灵活实现。无论何时您需要“向接口添加方法”,您都可以添加扩展方法。

回答by tloach

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.

多重继承是导致问题多于解决的问题之一。在 C++ 中,它适合给你足够的绳子来吊死自己的模式,但 Java 和 C# 选择了不给你选择的更安全的路线。最大的问题是,如果您继承多个类,这些类的方法具有被继承者未实现的相同签名的方法。它应该选择哪个类的方法?或者不应该编译?通常还有另一种方法可以实现大多数不依赖多重继承的东西。

回答by Thomas Hansen

MI is NOT bad, everybody that has (seriously) used it LOVES it and it doesNOT complicate the code! At least not anymore than other constructs may complicate the code. Bad code is bad code regardless of whether or not MI is in the picture.

MI 还不错,每个(认真地)使用过它的人都喜欢它,而且它不会使代码复杂化!至少不会像其他构造那样使代码复杂化。坏代码就是坏代码,不管图中是否有 MI。

Anyway, I've got a nice little solution for Multiple Inheritance I wanted to share, it's at; http://ra-ajax.org/lsp-liskov-substitution-principle-to-be-or-not-to-be.blogor you can follow the link in my sig... :)

无论如何,我想分享一个关于多重继承的不错的小解决方案,它在;http://ra-ajax.org/lsp-liskov-substitution-principle-to-be-or-not-to-be.blog或者您可以点击我签名中的链接... :)

回答by Jord?o

I created a C# post-compilerthat enables this kind of thing:

我创建了一个C# 后编译器来实现这种功能:

using NRoles;

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

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

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

public class FirstAndSecond : Does<RFirst>, Does<RSecond> { }

You can run the post-compiler as a Visual Studio post-build-event:

您可以将后编译器作为 Visual Studio 后构建事件运行:

C:\some_path\nroles-v0.1.0-bin\nutate.exe "$(TargetPath)"

C:\some_path\nroles-v0.1.0-bin\nutate.exe "$(TargetPath)"

In the same assembly you use it like this:

在同一个程序集中,您可以像这样使用它:

var fas = new FirstAndSecond();
fas.As<RFirst>().FirstMethod();
fas.As<RSecond>().SecondMethod();

In another assembly you use it like this:

在另一个程序集中,您可以像这样使用它:

var fas = new FirstAndSecond();
fas.FirstMethod();
fas.SecondMethod();

回答by supercat

If X inherits from Y, that has two somewhat orthogonal effects:

如果 X 继承自 Y,则有两个正交效应:

  1. Y will provide default functionality for X, so the code for X only has to include stuff which is different from Y.
  2. Almost anyplace a Y would be expected, an X may be used instead.
  1. Y 将为 X 提供默认功能,因此 X 的代码只需包含与 Y 不同的内容。
  2. 几乎在任何需要 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).

尽管继承提供了这两个特性,但不难想象在没有另一个的情况下,任何一个都可以使用的情况。我所知道的任何 .net 语言都没有直接实现第一个而不使用第二个的方法,尽管可以通过定义一个从未直接使用的基类来获得这样的功能,并且有一个或多个直接从它继承的类而不添加任何东西new(此类类可以共享其所有代码,但不能相互替代)。但是,任何符合 CLR 的语言都将允许使用提供接口的第二个特性(可替换性)而没有第一个特性(成员重用)的接口。

回答by ariel

i know i know even though its not allowed and so on, sometime u actualy need it so for the those:

我知道我知道即使它是不允许的等等,有时你确实需要它,因为这些:

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

like in my case i wanted to do this class b : Form (yep the windows.forms) class c : b {}

就像在我的情况下,我想做这个 class b : Form (是的 windows.forms) class c : b {}

cause half of the function were identical and with interface u must rewrite them all

因为一半的功能是相同的,并且你必须将它们全部重写

回答by Yogi

Yes using Interface is a hassle because anytime we add a method in the class we have to add the signature in the interface. Also, what if we already have a class with a bunch of methods but no Interface for it? we have to manually create Interface for all the classes that we want to inherit from. And the worst thing is, we have to implement all methods in the Interfaces in the child class if the child class is to inherit from the multiple interface.

是的,使用接口很麻烦,因为无论何时我们在类中添加方法,我们都必须在接口中添加签名。另外,如果我们已经有一个有一堆方法但没有接口的类怎么办?我们必须为我们想要继承的所有类手动创建接口。而最糟糕的是,如果子类要从多个接口继承,我们必须在子类中实现Interfaces中的所有方法。

By following Facade design pattern we can simulate inheriting from multiple classes using accessors. Declare the classes as properties with {get;set;} inside the class that need to inherit and all public properties and methods are from that class, and in the constructor of the child class instantiate the parent classes.

通过遵循 Facade 设计模式,我们可以使用访问器模拟从多个类继承。在需要继承的类内部使用{get;set;}将类声明为属性,所有公共属性和方法都来自该类,并在子类的构造函数中实例化父类。

For example:

例如:

 namespace OOP
 {
     class Program
     {
         static void Main(string[] args)
         {
             Child somechild = new Child();
             somechild.DoHomeWork();
             somechild.CheckingAround();
             Console.ReadLine();
         }
     }

     public class Father 
     {
         public Father() { }
         public void Work()
         {
             Console.WriteLine("working...");
         }
         public void Moonlight()
         {
             Console.WriteLine("moonlighting...");
         }
     }


     public class Mother 
     {
         public Mother() { }
         public void Cook()
         {
             Console.WriteLine("cooking...");
         }
         public void Clean()
         {
             Console.WriteLine("cleaning...");
         }
     }


     public class Child 
     {
         public Father MyFather { get; set; }
         public Mother MyMother { get; set; }

         public Child()
         {
             MyFather = new Father();
             MyMother = new Mother();
         }

         public void GoToSchool()
         {
             Console.WriteLine("go to school...");
         }
         public void DoHomeWork()
         {
             Console.WriteLine("doing homework...");
         }
         public void CheckingAround()
         {
             MyFather.Work();
             MyMother.Cook();
         }
     }


 }

with this structure class Child will have access to all methods and properties of Class Father and Mother, simulating multiple inheritance, inheriting an instance of the parent classes. Not quite the same but it is practical.

使用这个结构类 Child 将可以访问 Class Father 和 Mother 的所有方法和属性,模拟多重继承,继承父类的一个实例。不太一样,但很实用。