簡體   English   中英

如何編寫通用方法來復制均從同一抽象基類繼承的類的實例?

[英]How do I write a general method to copy instances of classes that all inherit from the same abstract base class?

我想按照以下代碼將一個畫筆實例的詳細信息復制到一個新實例:

private static Brush CopyBrush(Brush b)
        {
            Brush b1 = new Brush();

            // code to copy settings from b to b1

            return b1;
        }

我的困難是Brush是一個抽象類,因此我無法實例化它。 我有許多不同的類繼承自Brush,可以將其中的任何一個都傳遞給此方法。 繼承類都在Brush中使用相同的屬性,因此復制它們不是問題。 可以在調用源將返回值強制轉換回繼承類型。

如果保證所有派生類都具有帶有特定簽名的構造函數(例如,不帶任何參數),則可以基於其子Type實例實例化各自的子Type

Brush b1 = (Brush)Activator.CreateInstance(b.GetType());

如果不能保證這一點,則需要在Brush類中引入虛擬方法來創建當前類的新實例。 子類可以重寫它以調用合適的構造函數。

更具體地說,您的Brush類可以具有以下方法:

protected virtual Brush CreateBrushInstance()
{
    return (Brush)Activator.CreateInstance(GetType());
}

在需要不同構造函數參數的任何派生類中,重寫此方法並使用適當的參數值調用Activator.Create(Type, object[])方法

(這假定CopyBrushBrush類的方法。否則,對CreateBrushInstance方法使用internalpublic可見性。)

情況1:您所有從Brush派生的類都有一個公共的默認構造函數,而所有屬性都有一個公共的setter。

在這種情況下,一個通用方法就足夠了:

static TBrush Copy<TBrush>(this TBrush brush) where TBrush : Brush, new()
{
    return new TBrush() // <- possible due to the `new()` constraint ^^^
           {
               TypeOfHair = brush.TypeOfHair,
               NumberOfHairs = brush.NumberOfHairs,
               …
           };
}

情況2:不滿足上述一個或多個前提條件; 也就是說,沒有公共默認構造函數,或者至少一個屬性是不可公開設置的。

您可以使用以下模式:

abstract class Brush
{
    protected abstract Brush PrepareCopy();
    // replacement for public default ctor; prepares a copy of the derived brush
    // where all private members have been copied into the new, returned instance.

    public Brush Copy()
    {
        // (1) let the derived class prepare a copy of itself with all inaccessible
        //     members copied:
        Brush copy = PrepareCopy();

        // (2) let's copy the remaining publicly settable properties:
        copy.TypeOfHair = this.TypeOfHair;
        copy.NumberOfHairs = this.NumberOfHairs;

        return copy;
    } 
}

sealed class FooBrush : Brush
{
    public FooBrush(int somethingPrivate)
    {
        this.somethingPrivate = somethingPrivate;
        // might initialise other members here…
    }

    private readonly int somethingPrivate;

    protected override Brush PrepareCopy()
    {
        return new FooBrush(somethingPrivate);
    }
}

暫無
暫無

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

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