2012-02-16 27 views
5

我有以下代碼抽象類,如何避免代碼重複?

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public abstract void Invoke(string message); 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     // Do B 
    } 
} 

我有一個從基類繼承這些蘇巴和SUBB類,你可以看到,我有一個代碼,重複其自身被設置的時候,是有辦法把時間的設置移到基類?

回答

3

有很多可能的解決方案。

這取決於您何時想擁有此屬性集。

如果您想立即使用,您可以在Base類的構造函數中執行此操作。

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public abstract void Invoke(string message); 

    public Base() 
    { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do B 
    } 
} 
+0

在這種情況下SetTime應該受到保護。 – PVitt 2012-02-16 10:34:14

2

使用,而不是一個虛擬的方法:

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public virtual void Invoke(string message) { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
} 

internal class SubB : Base 
{ 
} 

您仍然可以覆蓋在你想要一個不同的實現子類的方法。

5

你可以做這樣的事情:

internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public void Invoke(string message){ 
     Time = DateTime.Now; 
     this.InvokeInternal(message); 
    } 
    protected abstract void InvokeInternal(string message); 
} 

internal class SubA : Base 
{ 
    protected override void InvokeInternal(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    protected override void InvokeInternal(string message) 
    { 
     // Do B 
    } 
} 
+1

+1。到底我會做什麼。 – Jehof 2012-02-16 10:34:18

2
internal abstract class Base 
{ 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public virtual void Invoke(string message) 
    { 
     Time = DateTime.Now; 
    } 

} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do B 
    } 
} 
+0

檢查基準參考:http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx – 2012-02-16 10:35:42

0

有很多的答案已經是。作爲替代方法(以及一些忍者)的方法,我會建議Lambda表達式與方法屬性一起使用。

在你的情況;

public class Base 
    { 
    public DateTime Time; 
    public string Message; 
    public string Log; 
    public Action<string> Invoke { get; set; } 

    public Base() 
    { 
     this.Invoke = InvokeDefault; 
    } 

    private void InvokeDefault(string message) 
    { 
     Time = DateTime.Now; 
    } 
    } 

這樣,我們爲base類提供默認行爲。隨着拉姆達表達式可以按如下方式創建具有不同Invoke方法實例..

var myInstance= new Base 
    { 
    Invoke =() => { Time = DateTime.Now.AddDays(7); } 
    }; 

的invoke方法只對Base類的實例覆蓋。這給了更多的靈活性,並有助於避免不必要的子類。

查看詳情請點擊這裏awesome post from Patrick Steele

0

有兩種實用選項,具體取決於您希望代碼合約的嚴格程度。

您可以將邏輯移動到虛擬方法中,並允許子類型在他們選擇時重載行爲。

internal abstract class Base 
{ 
    ... 
    public virtual void Invoke(string message) 
    { 
     Time = DateTime.Now; 
    } 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void Invoke(string message) 
    { 
     base.Invoke(message); 
     // Do B 
    } 
} 

但是,這確實使派生類型根本不能調用基本方法成爲可能。

如果是災難性的,如果基本功能不調用,您想要的預期行爲的更多的確定性,你可能希望通過提供一個注射點到基法的中間做一個更強的合同:

internal abstract class Base 
{ 
    ... 
    public void Invoke(string message) 
    { 
     Time = DateTime.Now; 
     this.InvokeCore(message); 
    } 

    protected abstract void InvokeCore(string message); 
} 

internal class SubA : Base 
{ 
    public override void Invoke(string message) 
    { 
     // Do A 
    } 
} 

internal class SubB : Base 
{ 
    public override void InvokeCore(string message) 
    { 
     // Do B 
    } 
}