2010-03-18 152 views
5

我學習設計模式和代碼示例我已經看到了約定​​,其中抽象類聲明的方法,例如:抽象方法簽名,繼承和「做」的命名約定

public abstract class ServiceBase { 
... 

public virtual object GetSomething(); 

然後

protected abstract object DoGetSomething(); 

我的問題是,爲什麼存在這兩種方法,因爲他們似乎達到同樣的目的。這是否使基類GetSomething()方法邏輯不能被繼承類重寫?但是再次,該方法被標記爲虛擬的,因此無論如何它都可以被覆蓋。這樣在要求派生類實現者實現抽象方法的時候有什麼用處呢?

+0

GetSomething應該是虛擬的嗎? – JaredPar

+0

是的,它絕對是虛擬的。 –

回答

4

一個常見原因是圍繞抽象方法進行標準處理。例如,也許抽象方法只能在某些情況下被調用 - 例如,樣條線被網狀化後。在這種情況下,在一個地方檢查_areSplinesReticulated是有意義的 - 公共GetSomething方法 - 而不是要求抽象方法的每個實現都執行自己的檢查。或者,也許GetSomething是90%的樣板,但需要一些額外的邏輯或只有派生類可以提供的關鍵信息。

這是Template Method模式的一種形式。

非虛擬GetSomething意味着每個派生類都獲得標準處理,並且只通過它們的自定義版本DoGetSomething進行參與。如果GetSomething是虛擬的,這意味着派生類可以繞過標準處理,如果他們想。這些都是一種可行的策略,具體取決於標準的GetSomething處理是否是類邏輯中不可或缺的一部分(例如不變量),還是基類想要給派生類賦予最大的靈活性。

0

我還沒有看到你所描述的版本,其中「GetSomething()」是虛擬的,但我已經看到了(和書面)班這樣的:

public abstract class Foo 
{ 
    protected abstract void DoBar(); 

    public void Bar() 
    { 
     // do stuff that has to happen regardless of how 
     // DoBar() has been implemented in the derived 
     // class 
     DoBar(); 
     // do other stuff 
    } 
} 

因爲「酒吧」不是虛擬的(並且我想你也可以將其封閉以確保)在調用「DoBar」方法之前和之後,您有機會「注入」代碼。這非常方便。