2013-05-14 20 views
5

在C#中,類A包含公共方法Foo(),它執行一些處理並返回一個值。 protected方法Bar(),也在類A執行與Foo()相同的邏輯,然後進行一些額外的處理,然後返回一個值。調用基本方法而不是覆蓋

爲避免重複代碼,Bar()調用Foo()並將返回值用作中間值。從A

class A 
{ 
    public virtual String Foo() 
    { 
    String computedValue; 
    // Compute the value. 
    return computedValue; 
    } 

    protected String Bar() 
    { 
    String computedValue; 
    String intermediateValue = Foo(); 
    /// More processing to create computedValue from intermediateValue. 
    return computedValue; 
    } 
} 

B繼承並重寫Foo()。覆蓋調用基類實現Bar()

class B : A 
{ 
    public override String Foo() 
    { 
    base.Bar(); 
    } 
} 

這(當然)進入一個無限循環,直到計算機內存不足,然後產生堆棧溢出異常。

最明顯的解決方案是用包含Foo膽量的私人FooInternals方法重寫A.然後修改Foo和Bar以使用該方法的結果。

有沒有辦法迫使A的Bar()調用A的Foo()而不是覆蓋?

(我幾乎可以肯定是太聰明在這裏,這正好完全針對多態,但我無法抗拒的衝動,嘗試推動我所知遠一點。)

回答

7

是否有辦法強制A的Bar()調用A的Foo()而不是覆蓋?

不直接。最簡單的重構是改變Foo到:

public virtual string Foo() 
{ 
    return FooImpl(); 
} 

private string FooImpl() 
{ 
    String computedValue; 
    // Compute the value. 
    return computedValue; 
} 

然後換Bar調用FooImpl而不是Foo

(這可能是你在你的「最明顯的解決方案」段落的意思 - 我錯過了一讀,我怕)

從根本上說,這只是其中的繼承是有問題的領域之一。當一個虛擬方法調用另一個方法時,需要記錄下來,以便子類可以避免造成問題 - 即使它覺得應該是是實現細節。正是這種事情讓我更喜歡構圖而不是繼承 - 當然這兩個都是合理的選擇。

+0

謝謝,我認爲這是最好的/明顯的方法。只是想知道我是否可能錯過了另一種選擇。 – ThatBlairGuy 2013-05-14 17:00:39

+1

@ThatBlairGuy:對不起,我設法錯過了描述這個問題的答案。哎呀:)但不,這就是你可以做的一切。 – 2013-05-14 17:02:42

+0

不用擔心,謝謝你驗證我沒有看到什麼。 – ThatBlairGuy 2013-05-14 17:15:13