由于多重继承是不好的(它使源更复杂),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的所有方法,那么将这两个方法组合成一个类就是最简单的解决方案.
为了避免冲突,这可以通过代码生成来完成,其中结果可以在之后改变,但是手动键入它是屁股中的纯粹痛苦.
考虑只使用组合而不是尝试模拟多重继承.您可以使用接口来定义构成合成的类,例如: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(); } }
由于多重继承是不好的(它使源更复杂),C#不直接提供这样的模式.但有时候拥有这种能力会有所帮助.
C#和.net CLR还没有实现MI,因为他们尚未总结如何在C#,VB.net和其他语言之间进行互操作,而不是因为"它会使源更复杂"
MI是一个有用的概念,未回答的问题是: - "当你在不同的超类中有多个公共基类时,你会怎么做?
Perl是我工作过的唯一一种MI工作和运作良好的语言..Net可能有一天会介绍它但是还没有,CLR确实已经支持MI,但正如我所说,除此之外还没有语言结构.
在此之前,你会遇到代理对象和多个接口:(
我创建了一个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();
您可以有一个实现IFirst和ISecond的抽象基类,然后仅从该基类继承。