C#中的流畅接口和多继承

时间:2013-08-02 21:34:15

标签: c# inheritance multiple-inheritance fluent-interface

此问题类似于 this one 。不同之处在于我希望有两个基类。

示例:

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类恰好具有与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");

如果:

,那将是超级

当我向CircleBox课程添加方法时,我不应该触及CircleAndBox课程。就像从单个类中定期继承一样,CircleAndBox应该自动继承CircleBox

中的所有公共方法

4 个答案:

答案 0 :(得分:4)

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

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传递给采用Box的方法,并期望在另一侧获得结果成为CircleAndBox

CircleAndBox cb = new CircleAndBox();

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

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

答案 1 :(得分:2)

继承意味着“是一个”。

BallRoundThingCircleRoundThingBoxSquareThingLamborghiniCarCarTransportBusBicycle也是Transport s。

如果它不是“是”关系,则不是继承。这就解释了为什么C#和Java不支持多继承,而且我在C ++中认识的大多数人都不鼓励这种继承。一个对象几乎不会同时出现两件事。

不要仅仅为了保存代码行而滥用继承。即使保存代码行是一个合法的目标(我不同意),它甚至是不必要的。另外两个结构可以帮助你。

首先,关于这种关系。你在寻找的是一种完全不同的关系。不是“是”,而是“可以用作”。这就是接口的用武之地。接口指定了对象的用途。所以你可以有两个接口IBoxICircle。然后,您的CircleAndBox事件可以实现两个接口,从而指定它可以同时用作两者。

其次,您可以再使用一种关系来简化生活。您不会保存代码行。但是,您将确保CircleAndBox始终具有CircleBox类中定义的正确行为。为此,您可以使用聚合以及委派模式。聚合是一种说“有一个”的关系。因此,让您的CircleAndBox类具有私有Circle对象和私有Box对象,然后通过调用相应的方法/实现ICircleIBox接口相应私有对象上的属性/事件,并返回它们返回的内容。

Presto,你有一个类有一个(聚合)Circle和Box实例来实际传递工作,通过使用相同的方法(委托)公开它们,因此可以用作(界面)圆圈作为方框。

答案 2 :(得分:1)

使用接口:

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
}

答案 3 :(得分:0)

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

例如:

interface iBox
{
  iBox Width(string width); //Assuming you want Box here and not Circle
}

然后你有Box

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对象。我不确定这是否有用。

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