2012-11-24 76 views
4

假設你有一個通用的接口,它定義了一個通用值和拷貝構造函數這樣的(更換ICloneable):如何實現泛型類的裝飾器的複製方法?

class BooleanHolder : ICopyable<Boolean, BooleanHolder> { 
    public BooleanHolder Copy() { 
     return new BooleanHolder(){ Value = Value }; 
    } 
} 

// T: type of value to hold, TU: type of the class itself 
interface ICopyable<T,TU> where TU: ICopyable<T,TU> { 
    T Value { get; set; } 
    TU Copy(); 
} 

這可能是一個布爾值保持這樣可以實現

現在出現了這樣的問題:你將如何定義一個容納另一個ICopyable的裝飾類?我不工作的想法是:

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> { 
    public DecoratingHolder<T,TU> Copy { 
     // won't compile as Value is of type T and not of type ICopyable<T,TU> 
     // as I expected - why is that? 
     return new DecoratingHolder<T,TU>(){ Value = Value.Copy }; 
    } 
} 

注意,我叫Copy也有複製ICopyable<T,TU>類型的值,這是故意的,以確保深層副本。

那麼,爲了使這個結構起作用,我需要改變什麼?

回答

3

您可能只需要添加一個約束。您可以定義ICopyable<T, TU> where TU : ICopyable<T, TU>,但在您的DecoratingHolder中,您絕不會明確約束TU,因爲它在DecoratingHolder上是這樣的。

更具體地說,我認爲這是該行的這一部分:

class DecoratingHolder<T,TU> : ***ICopyable<ICopyable<T,TU>*** 

這是導致該問題。您正在定義ICopyable<T,TU>類型,但TU未被限制爲ICopyable<T, TU>。 (也許可以從推斷出那個來自類的其餘部分的聲明/繼承,但編譯器不會)一旦添加約束,那麼編譯器知道Value是兼容的ICopyable<T,TU>類型。

這對我來說編譯罰款(曾與您所提供的僞代碼來解決其他一些小事情):

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
    where TU : ICopyable<T,TU> 
{ 
    public ICopyable<T,TU> Value { get; set; } 

    public DecoratingHolder<T,TU> Copy() { 
     return new DecoratingHolder<T, TU>(){ Value = Value }; 
    } 
} 

編輯:現在回想起來,你甚至需要在ICopyable該約束?似乎不會做太多,因爲無論如何您已經一般定義了傳出類型。除非你在其他地方有代碼,這取決於它由於某種原因返回ICopyable<T, TU>(無論如何,因爲它會返回一個強類型的TUBooleanHolderDecoratingHolder),然後考慮轉儲它。

interface ICopyable<T,TU> 
{ 
    T Value { get; set; } 
    TU Copy(); 
} 

class BooleanHolder : ICopyable<Boolean, BooleanHolder> 
{ 
    public bool Value { get; set; } 
    public BooleanHolder Copy() { 
     return new BooleanHolder(){ Value = Value }; 
    } 
} 

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
{ 
    public ICopyable<T,TU> Value { get; set; } 

    public DecoratingHolder<T,TU> Copy() { 
     return new DecoratingHolder<T, TU>(){ Value = Value }; 
    } 
} 

編輯:從您的評論需要深拷貝,保持約束則(你會需要它們),並調用ValueCopy(對不起,我一定是錯過了細節)

class DecoratingHolder<T,TU> : ICopyable<ICopyable<T,TU>, DecoratingHolder<T,TU>> 
    where TU : ICopyable<T,TU> 
{ 
    public ICopyable<T,TU> Value { get; set; } 

    public DecoratingHolder<T,TU> Copy() { 
     return new DecoratingHolder<T, TU>(){ Value = Value.Copy() }; 
    } 
} 

任何給定類的Copy方法應確保它們執行深度複製。(我建議重新命名CopyDeepCopy如果你的框架需要他們是深拷貝,你不想實現做淺灘意外)

+0

這實際上比我的方法更好,謝謝。 –

+0

@ChrisSinclair啊,對不起,我只是注意到我忘了提到實現深層副本的必要性。你會不會適應你的回答 – Bastian

+0

@Bastian對不起,我瞥見了那個細節。我添加了另一個編輯。 –

0

的鑄造制工作對我來說:

public DecoratingHolder<T, TU> Copy() 
    { 
     return new DecoratingHolder<T, TU>() { Value = (ICopyable<T, TU>)Value.Copy() }; 
    } 

我猜在這種情況下,編譯器不會確定TUICopyable<T, TU>是同一件事情。