2013-01-10 58 views
0

對不起,標題不好,但我的英語不太好。
假設下面的代碼(使用LINQPad在程序模式用於測試):OOP基礎知識:從派生類中創建base-ctor中的重寫對象

public class BaseClass 
{ 
    protected Settings settings; 

    public BaseClass() 
    { 
     this.settings = new Settings(); 
    } 

    public virtual void PrintSettings() 
    { 
     var t = settings.GetType(); 
     Console.WriteLine(string.Join(", ", t.GetProperties().Select(pi => pi.Name))); 
    } 

    public class Settings 
    { 
     public string BaseClassSetting { get { return "BaseClassSetting."; } } 
    } 
} 

呼喚 「新的BaseClass()PrintSettings();」。顯然會在Console中輸出「BaseClassSetting」。
讓我們獲得了從一個的BaseClass類:

public class InheritedClass : BaseClass 
{ 
    public new class Settings : BaseClass.Settings 
    { 
     public string InheritedClassSetting { get { return "InheritedClassSetting!"; } } 
    } 
} 

呼喚 「新InheritedClass()PrintSettings();」。仍將在控制檯中打印「BaseClassSetting」。
使代碼中使用了「新」版InheritedClass.Settings的唯一途徑是通過增加一個構造函數像

public InheritedClass() 
{ 
    this.settings = new Settings(); 
} 

有了這個額外的構造函數,它打印所需的「InheritedClassSetting,BaseClassSetting」來安慰。
現在的問題是:是否有可能使BaseClass-ctor始終使用實例對象的Settings-Class? (沒有在派生類中添加ctor)

回答

1

由於不好的做法,預計會出現問題的變通辦法。一般來說,我不會使用關鍵字new,不用介意嵌套類。通過讓基類接受從BaseClass.Settings繼承的泛型類型和無參數構造函數,可以刪除繼承類中的構造函數。顯然,這是不可讀的。

public class BaseClass<T> where T : BaseClass<T>.Settings, new() 
{ 
    protected Settings settings; 

    public BaseClass() 
    { 
     settings = new T(); 
    } 

    public virtual void PrintSettings() 
    { 
     var t = settings.GetType(); 
     Console.WriteLine(string.Join(", ", t.GetProperties().Select(pi => pi.Name))); 
    } 

    public class Settings 
    { 
     public string BaseClassSetting 
     { 
      get { return "BaseClassSetting."; } 
     } 
    } 
} 

public class InheritedClass : BaseClass<InheritedClass.Settings> 
{ 
    public new class Settings : BaseClass<InheritedClass.Settings>.Settings 
    { 
     public string InheritedClassSetting 
     { 
      get { return "InheritedClassSetting!"; } 
     } 
    } 
} 

注意就行了:

public new class Settings : BaseClass<InheritedClass.Settings>.Settings 

對仿製藥的爭論不要求你指定InheritedClass。我已經添加了它,因爲它已經很混亂了,我不想讓它變得更糟。

+0

不錯,但確實不太可讀;-)你將如何解決這個任務? – Sascha

+0

@Sascha取決於你將如何使用你的課程。例如,如果繼承不是必需的,那麼我只是使用一個接口來爲你所謂的'BaseClassSettings'和'InheritedSettings'(但不能讓一個從另一個派生)。另外,如果不是絕對必要的,我會避免將它們聲明爲嵌套類。 – Mir

1

不,因爲你不能擁有「虛擬類型」。

有幾種方法可以嘗試實現您在此處所做的工作,但所有這些方法都需要InheritedClass在某些時候明確引用其自己的版本Settings