当前位置:  开发笔记 > 编程语言 > 正文

C#中的多重继承

如何解决《C#中的多重继承》经验,为你挑选了4个好方法。

由于多重继承是不好的(它使源更复杂),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.


编辑

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

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

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

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

    编写一个继承自TextTcpClient的新类,并以某种方式实现IComponent(尚未实际尝试过).

在这两种情况下,您都需要按方法而不是按类进行工作.既然你知道我们需要TextTcpClient和Component的所有方法,那么将这两个方法组合成一个类就是最简单的解决方案.

为了避免冲突,这可以通过代码生成来完成,其中结果可以在之后改变,但是手动键入它是屁股中的纯粹痛苦.



1> Chris Wenham..:

考虑只使用组合而不是尝试模拟多重继承.您可以使用接口来定义构成合成的类,例如:ISteerable隐含类型属性SteeringWheel,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();
    }
}


这就是重点 - 像这样的想法可以减轻构图.
是的,但是在某些用例中您确实需要将这些方法作为主要对象的一部分
不幸的是,在扩展方法中无法访问成员变量数据,因此您必须将它们公开为内部或(ug)public,尽管我认为按合同组合是解决多重继承的最佳方法.
很好的答案!简洁,易懂,非常有用的插图.谢谢!
我们可能想在调用“停止”之前检查“ myCar”是否已完成向左转向。如果myCar速度过快时应用Stop,则可能会翻转。:D

2> IanNorton..:

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

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

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

Perl是我工作过的唯一一种MI工作和运作良好的语言..Net可能有一天会介绍它但是还没有,CLR确实已经支持MI,但正如我所说,除此之外还没有语言结构.

在此之前,你会遇到代理对象和多个接口:(


CLR不支持多实现继承,只支持多接口继承(C#也支持).
@MandeepJanjua我没有声称任何这样的事情,我说'很可能会介绍它'事实仍然是ECMA标准CLR确实提供了IL机制的多重继承,只是没有充分利用它.
@Jordão:为了完整起见:编译器可以为CLR中的类型创建MI.它确实有它的警告,例如它不符合CLS.有关更多信息,请参阅此(2004)文章http://blogs.msdn.com/b/csharpfaq/archive/2004/03/07/why-doesn-tc-support-multiple-inheritance.aspx
@MrHappy:非常有趣的文章.我实际上已经研究过C#的某种[Trait Composition](http://codecrafter.blogspot.com/2011/05/nroles-experiment-with-roles-in-c.html),看一看.
FYI多重继承也不错,并且不会使代码变得复杂.我以为我会提到它.

3> Jordão..:

我创建了一个C#post-compiler来支持这种事情:

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, Does { }

您可以将后编译器作为Visual Studio post-build-event运行:

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

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

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

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

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



4> Joel Coehoor..:

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


@leppie-“每次我向其中一个接口添加一个方法时,我也需要更改类FirstAndSecond。” 此解决方案无法解决原始问题的这一部分,对吗?
您将不得不编辑抽象类,但是不必编辑依赖于它的任何其他类。责任制止于此,而不是继续级联到整个班级。
推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有