2016-05-12 31 views
0

我相信這一定是重複的,但我無法找到答案:尋找克隆()實現與得到的返回類型

如果我有兩類:

public class BASE 
{ 
    public BASE() {}; 
    public abstract BASE clone(); 
} 


public class CHILD : BASE 
{ 

    public CHILD() : base() {} 
    public override BASE clone() 
    { 
     return new CHILD(); 
    } 
} 

我有每次我想克隆一個像CHILD類型的對象時進行顯式轉換:

var a = new CHILD(); 
CHILD b = a.clone() as CHILD; 

有沒有辦法避免這種轉換? 我希望能寫:

var original = new CHILD(); 
BASE copy1 = original.clone(); 
CHILD copy2 = original.clone(); 

這是可能的C#?

+0

由於多態性,我認爲可以用BASE而不是'CHILD'。你爲什麼想要'CHILD'類型?但有一種方法可以做到這一點,雖然...使用方法*隱藏*而不是方法*覆蓋* – Ian

+0

多態性允許我寫'CHILD c = new CHILD(); BASE b = c'但不是相反。我無法將'BASE'對象分配給'CHILD'變量。這就是爲什麼當我克隆CHILD時,我總是必須進行轉換。 –

+0

我看,在這種情況下,使用'generic'是你的選擇 – Ian

回答

3

有沒有辦法避免這種轉換?

不是通過重載Clone - 你不能通過改變它的返回類型來重載一個方法。如果要強制執行所有繼承類的這種行爲,你可以讓BASE通用

public class CHILD : BASE 
{ 

    public CHILD() : base() {} 
    public BASE clone() { return this.cloneChild();} 
    public CHILD cloneChild() 
    { 
     return new CHILD(); 
    } 
} 

public abstract class BASE<T> where T:BASE<T> 
{ 
    public BASE() {} 
    public abstract T clone(); 
} 


public class CHILD : BASE<CHILD> 
{ 

    public CHILD() : base() {} 
    public override CHILD clone() 
    { 
     return new CHILD(); 
    } 
} 
1

如果您需要在CHILD類型,而不是BASE類型改爲使用不同的方法clone,那麼你需要做的方法隱藏而不是方法覆蓋。您應該刪除override關鍵字,並使用new代替:

public class BASE 
{ 
    public BASE() {}; 
    public abstract BASE clone(); 
} 

public class CHILD : BASE 
{ 

    public CHILD() : base() {} 
    public new CHILD clone() 
    { 
     return new CHILD(); 
    } 
} 
+1

只要你沒有通過'BASE'類型的變量引用'CHILD' - 你就會在'BASE'上調用'clone'方法,這可能無法正確地克隆'CHILD'實例。 –

+0

@JamesThorpe我的歉意,我的意思是實際上'CHILD' - 感謝評論 – Ian

+1

你仍然有同樣的問題。如果你有一個'CHILD'的實例,但是代碼將它存儲在一個'BASE'變量中,你最終會在一個'CHILD'實例上調用'BASE.clone'。有可能這不會產生正確的行爲。 –

0

C#不支持返回類型協方差。你可以嘗試這個解決方法(使用泛型):

public class Base<T> { 
    public abstract T Clone() 
} 

public class Child : Base<Child> { 
    public override Child Clone() { 
     return ...; 
    } 
}