2017-06-19 14 views
2

我有幾個類從我希望更改屬性和方法的實現的基類繼承。我還要求基類和所有子類都是多態的,所以我以後可以創建一個實現特定接口的任何類型的集合。什麼是適當的方式來改變子類的屬性訪問器,同時保持多態?

當我創建實現接口的類的實例時,我想使用該類(由接口實現)而不是基類的屬性和方法。

這是我的簡單實現,它提供了所需的輸出,但確實有一個代碼的氣味問題的...

class Program 
{ 
    static void Main(string[] args) 
    { 
     IGrid one = new TextField(); 
     IGrid two = new SelectList(); 
     one.Click(); 
     two.Click(); 
     Console.WriteLine(one.Text); 
     Console.WriteLine(two.Text); 
     Console.ReadLine(); 
    } 
} 

public interface IGrid { 
    string Text { get; set; } 
    void Click(); 
} 

public class Control : IGrid { 
    public string Text { 
     get { return "Hello Control!"; } 
     set { } 
    } 

    public virtual void Click() { 
     Console.WriteLine("In the Control!"); 
    } 
} 

public class SelectList : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello Select!"; 
     } 
     set { Number = int.Parse(value); } 
    } 

    public override void Click() { 
     Console.WriteLine("In the Select!"); 
    } 
} 

public class TextField : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello TextField!"; 
     } 
     set { Number = int.Parse(value); } 
     } 

    public override void Click() 
    { 
     Console.WriteLine("In the TextField!"); 
    } 
} 

這工作,但感覺有點凌亂其在控制類空集。

是否有一種更清晰的方法來解決這類問題而不影響子類上的特定屬性實現?

非常感謝,

+1

恕我直言,如果你不打算實現一個接口,那麼不要假裝實現一個接口。對你的班級的最終用戶有一些同情心。另外,你的例子對我來說沒有意義,1.如果有人試圖將字符串Text屬性設置爲非整數值,則會拋出異常,並且2.不改變Text屬性當有人設置它。你有更現實的例子嗎?完全不清楚爲什麼你想要這樣做,而不是僅僅使用附加屬性創建新界面。 –

+0

嗨Rufus。對不起,現在還不清楚。我還在學習。最終,我想最終得到類似'List GridItems'的東西,然後就可以添加不同類型的網格項目,比如'SelectList'和'TextField'。我希望能夠訪問這些類的方法和屬性的特定實現,而不是任何基類。看起來很奇怪的'set'評估者只是表明我想要改變子類的實現。正如我所說,方法可能是完全錯誤的,我願意提供更好的建議。謝謝, – Konzy262

回答

1

好了,第一件事就是當你第一次設置一個屬性(好像你是做文字爲數字),您不應該更改其他財產。這是一個巨大的代碼氣味,因爲它是一種副作用。你應該總是直接處理你打算的屬性。

public class SelectList : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello Select!"; 
     } 
     // This is bad, someone after you may not know that this has a side effect 
     set { Number = int.Parse(value); } 
    } 
} 

其次,屬性可以是虛擬的,就像一個方法,讓你的標記文本屬性爲虛擬和在派生類中overridding將使多態性的工作意圖的方式。通過new關鍵字「隱藏」將需要您將接口轉換爲其特定的類,以便獲得該類的實現。

public class Control : IGrid 
    { 
     public virtual string Text 
     { 
      get { return "Hello Control!"; } 

     } 

     public virtual void Click() 
     { 
      Console.WriteLine("In the Control!"); 
     } 
    } 
public class SelectList : Control, IGrid 
{ 
    public int Number { get; set; } 
    public override string Text 
    { 
     get 
     { 
      return "Hello Select!"; 
     } 

    } 

    public override void Click() 
    { 
     Console.WriteLine("In the Select!"); 
    } 
} 

第三,你不必在接口上設置setter。你只需要一個getter,只需要實現它。

public interface IGrid 
    { 
     string Text { get; } 
     void Click(); 
    } 

最後,如果你總是要重寫方法或屬性,並永遠不會直接創建基類(使用新的),那麼你應該,如果你有共同實施考慮使用抽象類(例如,在至少有一種方法或屬性不會更改),或者不打擾基類,因爲反正沒有使用任何代碼。

// Abstract class 
public abstract class Control : IGrid 
{ 
    // Property that is not overridden but is shared 
    public int Number { get; set; } 

    public abstract string Text 
    { 
     get; 

    } 

    public abstract void Click(); 
} 
public class SelectList : Control 
{ 
    // Don't need the Number property here, base class has it 

    public override string Text 
    { 
     get 
     { 
      return "Hello Select!"; 
     } 

    } 

    public override void Click() 
    { 
     Console.WriteLine("In the Select!"); 
    } 
} 

// Need everything in this class, but if it is all different anyways 
// then base class is kind of a waste 
public class TextField : IGrid 
{ 
    public int Number { get; set; } 
    public string Text 
    { 
     get 
     { 
      return "Hello TextField!"; 
     } 
    } 

    public void Click() 
    { 
     Console.WriteLine("In the TextField!"); 
    } 
} 
相關問題