2009-06-26 46 views
3

在下面的示例中,派生類的作者將期望調用base.Add()。如果它發生在第一,基地可以做一種代碼。如果最後發生,基地可以做另一種邏輯(見樣本)。我似乎不可能有兩種方式。簡單的解決方法是停止調用基本方法,因爲基礎永遠不會知道它是被第一次,最後還是中間還是兩次調用!何時調用base.method()以及base.method()中應該放置什麼代碼?

什麼是面向對象的方式來處理這個問題?我應該簡單地停止將代碼放入基本方法中,因爲我永遠不會知道前置條件和後置條件嗎?

編輯:目標是有一個做CRUD操作的業務對象類。重複的代碼將被移動到基類。例如,檢查在添加記錄之前是否有業務對象的id爲0,並在保存後檢查業務對象的id是否大於0。

namespace StackOverFlowSample 
{ 
    class BusinessObjectBase 
    { 
     private bool _isNew; 
     private int _id; 
     public virtual void Add(string newAccount) 
     { 
      //Code that happens when subclasses run this method with the 
      //same signature 

      //makes sense if base is called 1st 
      if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state"); 

      //makes sense if bae is called 2nd 
      if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state"); 
     } 
    } 
    class BusinessObject : BusinessObjectBase { 
     public override void Add(string newAccount) 
     { 
      //doesn't make sense, because base will need to be called again. 
      base.Add(newAccount);//pre validation, logging 

      //Save newAccount to database 

      //doesn't make sense, because base has already been called 
      base.Add(newAccount); //post validation, logging 
     } 
    } 
} 

回答

3

如果你想要一個安全的方式來介紹pre - 和後置條件的檢查,你可以添加非虛,反而有另一種方法(AddInternal或類似的東西)的派生類可以(或必須?)覆蓋:

namespace StackOverFlowSample 
{ 
    abstract class BusinessObjectBase 
    { 
     private bool _isNew; 
     private int _id; 

     protected abstract void AddInternal(string newAccount); 
     public void Add(string newAccount) 
     { 
      if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state"); 
      AddInternal(newAccount);  
      if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state"); 
     } 
    } 
    class BusinessObject : BusinessObjectBase { 
     protected override void AddInternal(string newAccount) 
     { 
      //Save newAccount to database 
     } 
    } 
} 
+0

基本上和我一樣的答案,除了一分鐘之前......我可以建議你設置AddInternal保護嗎? – 2009-06-26 14:17:10

+0

@bruno:絕對; AddInternal應該受到保護,這是我的疏忽。感謝您指出。 – 2009-06-26 14:21:31

2

很難按照你想要什麼方面的具體例子,但一個解決辦法是經常使用的模板圖案,而不是 - 不問子類調用基類,而是提供一個單獨的抽象方法,它不能做任何有用的工作除非它調用基類中的(非虛擬)方法 - 或者它只是返回模板方法可用來調用真實方法的東西。

我覺得繼承變得更容易理解,如果一切要麼是抽象或密封的 - 也就是說你無論是來覆蓋它,你不能調用基方法,也不能覆蓋它開始。當然也有例外,但這是一個很好的起點。這也是一種看待事物的功能方式 - 你可能會發現你可以在沒有繼承的情況下實際上做到,並且只需要適當的代表來提供專業化;

1

難道是有意義的東西上線:

class BusinessObjectBase 
{ 
    public void Add(string newAccount) 
    { 
     if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state"); 

     AddOperation(newAccount); 

     if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state"); 
    } 

    protected void virtual AddOperation(string newAccount) 
    { 
     // Code from base AddOperation 
    } 

} 
class BusinessObject : BusinessObjectBase { 
    protected override void AddOperation(string newAccount) 
    { 
     //custom AddOperation 
    } 
} 
相關問題