簡體   English   中英

流利的接口和C#中的多重繼承

[英]Fluent interfaces and multiple inheritance in C#

這個問題與類似。 區別在於我想擁有兩個基類。

例:

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 and 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繼承所有公共方法。

CircleAndBox從這兩個類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;

繼承的意思是“是”。

BallRoundThing CircleCircleRoundThing Box是一個SquareThing LamborghiniCarCarTransport BusBicycle也是Transport

如果不是“是”關系,則它不是繼承。 這就是為什么在C#和Java中不支持多重繼承的原因,而我在C ++中認識的大多數人都不建議使用多重繼承。 一個對象幾乎永遠不會是兩件事。

不要僅僅為了保存代碼行而濫用繼承。 即使保存代碼行是一個合法的目標(我不同意),也沒有必要。 另外兩個構造可以在這里為您提供幫助。

首先,關於關系。 您正在尋找的是完全不同的關系。 不是“是”,而是“可以用作”。 這就是接口進入的地方。接口指定對象可以用作什么。 因此,您可以有兩個接口IBoxICircle 然后,您的CircleAndBox事物可以實現這兩個接口,因此指定可以同時使用這兩個接口。

其次,您可以使用一種以上的關系來簡化生活。 您將不會保存代碼行。 但是,您將確保CircleAndBox始終具有正確的行為,這些行為在CircleBox類中定義。 為此,您可以將聚合與委托模式一起使用。 聚合是一個表示“具有”的關系。 因此,使您的CircleAndBox類具有一個專用的Circle對象和一個專用的Box對象,然后只需在各個專用對象上調用相應的方法/屬性/事件,即可實現ICircleIBox接口,並返回它們返回的值。

Presto,您有一個具有 (聚合)Circle和Box實例的類, 可以將工作實際傳遞給該實例,該實例通過具有相同的方法(委托)公開這些實例,因此可以用作 Circle的(接口) 框。

使用界面:

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
}

我不認為您可以完全如您所願,因為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對象。 我不確定這將達到目的。

另外,如果您不控制要繼承的類中的至少一個,則此方法將無效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM