2011-05-26 59 views
4

問題最明顯的情況是功能克隆(只是示例傢伙)。假設您有BaseClass和DerivedClass - 除非我錯過了兩個函數(分別爲每個類的克隆)分別創建BaseClass和DerivedClass,但實際返回對象。 這是如果你想與「真正的」類工作的問題。如何處理不同類型結果的覆蓋函數?

到目前爲止,我看到的只有兩種方法可以解決這個問題:

每次施放函數的結果適當類

var real_stuff = (RealStuff)x.Clone(); // I want real stuff 

2.提供第二個功能,所以您將擁有克隆(如果您在基礎級別工作)和CloneThis(如果您希望在給定的職業級別工作,結果將從班級變爲班級)

public override object Clone() 
    { 
     return CloneThis(); 
    } 
    public RealStuff CloneThis() 
    { 
     return new RealStuff(this); 
    } 

第一個是醜陋的,第二個是令人厭煩的。

問題:你如何處理這個問題?

另一件事 - 請評論這一點以及如果你喜歡 - 是爲什麼當重寫函數簽名檢查是如此嚴格?除了「因爲它是按照這種方式設計的」,還是Eric Lippert最喜歡的「因爲每個功能都需要...」;-)我沒有看到允許覆蓋功能改變的結果類型的技術問題(以及邏輯等)IF重寫函數結果是從原始函數結果類型派生的。

例子:

class ClassA 
    { 
    public virtual ClassA GetIt() ... 
    } 

    class ClassB : ClassA 
    { 
    public override ClassB GetIt() ... 
    } 

目前,它是不正確的代碼,但我認爲這在技術上可能是,因爲ClassB的是從ClassA的派生。無論你如何處理輸出,「接收器」都需要ClassA,所以ClassB滿足了這個要求。

所以,你可以寫:

ClassA class_a_b = new ClassB(); 
    ClassB class_b_b = new ClassB(); 

    ClassA result1 = class_b_b.GetIt(); 
    ClassA result2 = class_a_b.GetIt(); 
    ClassB result3 = class_b_b.GetIt(); 
    // incorrect, derived GetIt would be called OK, 
    // but the signature is taken from ClassA 
    ClassB result4 = class_a_b.GetIt(); 

我也並不認爲有這種能力的人會被行爲感到驚訝,恕我直言這是一致的。

請保留您的答案on-topic,「您不應該使用ICloneable」是不是的主題。謝謝。

+0

您是否考慮過公開虛擬T Clone 方法,該方法可以被覆蓋並在沒有推斷出的類型時被調用克隆(myObj)? – Mart 2011-05-26 07:13:43

+1

可能的重複http://stackoverflow.com/questions/536349/why-no-icloneablet和http://stackoverflow.com/questions/1048884/c-overriding-return-types – 2011-05-26 07:16:54

+0

@Paolo Tedesco,第二個是好的謝謝你。這個問題是** DUPLICATE **,我該如何關閉它? – greenoldman 2011-05-26 07:29:07

回答

3

檢查這兩個問題:

基本上,要對付這種方式定義與相應的返回類型,例如通用接口

interface ICloneable<T> { 
    T Clone(); 
} 

然而,這並沒有讓您使用的接口爲基本類型,因爲ICloneable < ClassOne>和ICloneable < ClassTwo>是兩回事。

只有通過返回類型纔有「技術上可行」的功能,事實上CLR允許這樣做,但C#不會,可能是因爲不可能總是推測正確的調用超載。 (實際上,使用C#,你可以用隱式轉換運算符來完成它們:它們被編譯爲名稱爲op_Implicit和不同返回類型的函數)。

+0

第二個環節很棒,我已經閱讀過,不僅接受的答案好,還有其他答案。我注意到至少有4個固體(!)方法。當然,開箱即用這種能力會更好。只要對你的陳述發表評論:「不可能總是猜測正確的超載呼叫。」它不是重載,它重載(我問覆蓋),它總是知道調用哪個函數,它是編譯時間級別的函數。 – greenoldman 2011-05-26 07:37:00