C# C语言中的Fluent接口与多重继承#

C# C语言中的Fluent接口与多重继承#,c#,inheritance,multiple-inheritance,fluent-interface,C#,Inheritance,Multiple Inheritance,Fluent Interface,这个问题类似于。区别在于我想要两个基类 示例: public class Circle { private string _radius { get; set; } public Circle Radius(string radius) { _radius = radius; return this; } } public class Box { private string _width { get; set; }

这个问题类似于。区别在于我想要两个基类

示例:

public class Circle
{
    private string _radius { get; set; }

    public Circle Radius(string radius)
    {
        _radius = radius;
        return this;
    }
}

public class Box
{
    private string _width { get; set; }

    public Circle Width(string width)
    {
        _width = width;
        return this;
    }
}

public class CircleAndBox : Circle, Box // Can't do in c#
{
    // should contain methods from both Circle and Box, but return CircleAndBox
}
也许圆圈和盒子不是最好的例子。基本上,它们表示具有不同属性和方法的类。类CircleAndBox恰好与Circle和Box具有相同的属性和方法。CircleAndBox可能具有在Circle或Box中都不存在的其他属性和方法

期望的结果

我应该能够写:

var circle = new Circle().Radius("5");
var box = new Box().Width("6");
var circleAndBox = new CircleAndBox().Radius("5").Width("6");
如果:

public class Circle
{
    private string _radius { get; set; }

    public Circle Radius(string radius)
    {
        _radius = radius;
        return this;
    }
}

public class Box
{
    private string _width { get; set; }

    public Circle Width(string width)
    {
        _width = width;
        return this;
    }
}

public class CircleAndBox : Circle, Box // Can't do in c#
{
    // should contain methods from both Circle and Box, but return CircleAndBox
}
当我向
Circle
Box
类添加方法时,我不应该触摸
CircleAndBox
类。就像从单个类进行常规继承一样,
CircleAndBox
应该自动从
Circle
Box
使用接口继承所有公共方法:

IBox和ICircle

public interface IBox
{
    Circle Width(string width)
}

public interface ICircle
{
    Circle Radius(string radius)
}

public class Circle : ICircle
{
    private int _radius { get; set; }

    public Circle Radius(string radius)
    {
        _radius = radius;
        return this;
    }
}

public class Box : IBox
{
    private int _width { get; set; }

    public Circle Width(string width)
    {
        _width = width;
        return this;
    }
}

public class CircleAndBox : ICircle, IBox
{
    // should contain methods from both Circle and Box, but return CircleAndBox
}
使用接口:

IBox和ICircle

public interface IBox
{
    Circle Width(string width)
}

public interface ICircle
{
    Circle Radius(string radius)
}

public class Circle : ICircle
{
    private int _radius { get; set; }

    public Circle Radius(string radius)
    {
        _radius = radius;
        return this;
    }
}

public class Box : IBox
{
    private int _width { get; set; }

    public Circle Width(string width)
    {
        _width = width;
        return this;
    }
}

public class CircleAndBox : ICircle, IBox
{
    // should contain methods from both Circle and Box, but return CircleAndBox
}

Have
CircleAndBox
继承两个类,而是引用这些类的对象。它必须重新定义每个类中的方法。您可以将隐式转换添加到
,以便在需要引用这些对象的上下文中使用它

public class CircleAndBox
{
    public Circle Circle { get; private set; }
    public Box Box { get; private set; }

    public CircleAndBox()
    {
        Circle = new Circle();
        Box = new Box();
    }

    public CircleAndBox Radius(string radius)
    {
        Circle.Radius(radius);
        return this;
    }

    public CircleAndBox Width(string width)
    {
        Box.Width(width);
        return this;
    }

    public static implicit operator Circle(CircleAndBox self)
    {
        return self == null ? null : self.Circle;
    }

    public static implicit operator Box(CircleAndBox self)
    {
        return self == null ? null : self.Box;
    }
}
请注意,隐式转换不会保留对象的类型,因此不应使用此技术将
CircleAndBox
传递给使用
框的方法,并期望另一侧的结果是
CircleAndBox

CircleAndBox cb = new CircleAndBox();

// Implicit conversion, b contains a Box object.
Box b = cb;

// Compile-time error CS0030.
cb = (CircleAndBox)b;

Have
CircleAndBox
继承两个类,而是引用这些类的对象。它必须重新定义每个类中的方法。您可以将隐式转换添加到
,以便在需要引用这些对象的上下文中使用它

public class CircleAndBox
{
    public Circle Circle { get; private set; }
    public Box Box { get; private set; }

    public CircleAndBox()
    {
        Circle = new Circle();
        Box = new Box();
    }

    public CircleAndBox Radius(string radius)
    {
        Circle.Radius(radius);
        return this;
    }

    public CircleAndBox Width(string width)
    {
        Box.Width(width);
        return this;
    }

    public static implicit operator Circle(CircleAndBox self)
    {
        return self == null ? null : self.Circle;
    }

    public static implicit operator Box(CircleAndBox self)
    {
        return self == null ? null : self.Box;
    }
}
请注意,隐式转换不会保留对象的类型,因此不应使用此技术将
CircleAndBox
传递给使用
框的方法,并期望另一侧的结果是
CircleAndBox

CircleAndBox cb = new CircleAndBox();

// Implicit conversion, b contains a Box object.
Box b = cb;

// Compile-time error CS0030.
cb = (CircleAndBox)b;

我认为你不能完全按照你的期望去做,因为C#(和.Net一般)不支持类的多重继承。您可以从一个类继承并实现一个接口

例如:

interface iBox
{
  iBox Width(string width); //Assuming you want Box here and not Circle
}
然后你有一个盒子

class Box : iBox ...
现在你可以

public class CircleAndBox : Circle, iBox
{
private Box _helper;
public iBox Width(string width) { _helper.Width(width); return this; }
}
这并不完全是你想要的,但我认为这是C#所允许的。如果您愿意使用弱类型,那么还有一种委托方法可以将内容传递给_helper,而无需显式实现每个方法。但是,使用直接委托,您不会返回CircleAndBox对象,而是返回_helper对象。我不确定这是否能达到目的


另外,如果您不控制至少一个要继承的类,那么这将不起作用。

我认为您不能完全按照您的期望来做,因为C#(通常是.Net)不支持类的多重继承。您可以从一个类继承并实现一个接口

例如:

interface iBox
{
  iBox Width(string width); //Assuming you want Box here and not Circle
}
然后你有一个盒子

class Box : iBox ...
现在你可以

public class CircleAndBox : Circle, iBox
{
private Box _helper;
public iBox Width(string width) { _helper.Width(width); return this; }
}
这并不完全是你想要的,但我认为这是C#所允许的。如果您愿意使用弱类型,那么还有一种委托方法可以将内容传递给_helper,而无需显式实现每个方法。但是,使用直接委托,您不会返回CircleAndBox对象,而是返回_helper对象。我不确定这是否能达到目的

此外,如果您不控制至少一个要继承的类,这将不起作用。

继承意味着“是一个”

是一种
圆形物体
<代码>圆形
是一种
圆形
<代码>框
是一个
平方
<代码>兰博基尼是一辆
汽车
汽车
是一辆
交通工具
<代码>公共汽车和自行车也是交通工具

如果它不是一个“是”关系,那么它就不是继承。这就是为什么C++和java中不支持多重继承的解释,而我在C++中所了解的大多数人都不赞成。一个物体几乎不可能同时是两件东西

不要仅仅为了保存代码行而滥用继承。即使保存代码行是一个合理的目标(我不同意这一点),它甚至没有必要。在这方面,还有两个构造可以帮助您

首先,关于关系。你要找的是一个完全不同的关系。不是“是a”,而是“可以用作”。这就是接口的用武之地。接口指定对象可以用作什么。因此,您可以有两个接口
IBox
ICircle
。然后,您的
CircleAndBox
东西可以实现这两个接口,从而指定它可以同时用作这两个接口

第二,你可以多使用一种关系,让生活更轻松。您将不会保存代码行。但是,您将确保您的
CircleAndBox
始终具有在
Circle
Box
类中定义的正确行为。为此,可以使用聚合和委派模式。聚合是一种表示“有一个”的关系。因此,让您的
CircleAndBox
类拥有一个私有的
Circle
对象和一个私有的
Box
对象,然后只需在各自的私有对象上调用相应的方法/属性/事件,并返回它们返回的内容,即可实现
ICircle
IBox
接口

实际上,您有一个类,它有一个(聚合)圆和盒子实例来实际传递工作,它通过使用相同的方法(委托)来公开这些实例,因此可以用作(接口)圆和盒子。

继承意味着“是一个”

B