2012-08-10 33 views
0

請考慮以下幾點:非常基本的 C#代碼。在C#抽象中設置構造函數

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Random random = new Random(); 

      for (int i = 1; i <= 100; i++) 
      { 
       int num = random.Next(1000); 
       string it_type; 

       if (num == 666) 
       { 
        System.Console.Write("Antichrist/satanistic trips get. Enjoy! "); 
        JonSkeet technician = new JonSkeet(); // Needs more Super::$tatic 
        technician.setup(); 
        it_type = technician.getITType(); 
       } 
       else 
       { 
        Whisperity technician = new Whisperity(); 
        technician.setup(); 
        it_type = technician.getITType(); 
       } 

       System.Console.WriteLine(it_type + "... Prepare for next iteration."); 
      } 

      System.Console.ReadLine(); 
     } 
    } 

    abstract public class ITTechnician 
    { 
     protected string itt_type = "Noname person."; 
     protected bool isJonSkeet = false; 

     public string getITType() 
     { 
      return this.itt_type; 
     } 

     abstract public void setup(); 
    } 

    public class JonSkeet : ITTechnician 
    { 
     public override void setup() 
     { 
      this.itt_type = "Jon Skeet"; 
      this.isJonSkeet = true; 
     } 
    } 

    public class Whisperity : ITTechnician 
    { 
     public override void setup() 
     { 
      this.itt_type = "Whisperity"; 
      this.isJonSkeet = false; 
     } 
    } 
} 

我如何將能夠建立一個構造函數的方式,抽象類(abstract public void?)需要它,我沒有打電話給technician.setup();因爲構造需要設置兩個照顧內部變量。如果我調用類的函數同名的類本身,我得到以下錯誤:

Error 1 'Whisperity': member names cannot be the same as their enclosing

而且,我的其他問題是關於優化。有沒有一種方法來定義technicianif結構,以便像下面這樣就可以執行外(這將省去具有兩倍classType technician = new classType();線,或者是在C#它unbypassable?)

string it_type; 
// Register 'technician' as a variable here. 
if (num = 666) 
{ 
    technician = new JonSkeet(); 
} 
else 
{ 
    technician = new Whisperity(); 
} 

it_type = technician.getITType(); 
System.Console.WriteLine(it_type + "..."); 
+1

@exacerbatedexpert:你不能強制派生類來實現一個consructor,但是你可以強制它在抽象類中調用一個構造函數。如果抽象類沒有默認構造函數,則子類*必須*明確地調用構造函數。 – 2012-08-10 22:27:48

回答

2

回答你的問題

您可以在抽象類中爲參數提供構造函數。

abstract public class ITTechnician 
{ 
    public ITTechnician(string itt_type, bool isJonSkeet) 
    { 
     this.itt_type = itt_type; 
     this.isJonSkeet = isJonSkeet; 
    } 
} 

構建一個JonSkeet(如果只有它是那麼容易!)對類設計

JonSkeet jon = new JonSkeet("Jon Skeet", true); 

建議在一個側面說明,我知道這是一個簡單的問題,但是如果基類持有可以區分從它繼承的類的信息,那麼您不會很好地使用對象方向。

具體這樣的設計會使你不喜歡的東西

ITTechnician itt = GetSomeInstance(); 

if (itt.IsJonSkeet) 
{ 
    BehaviorA(); 
else 
{ 
    BehaviorB(); 
} 

這是更乾淨做這樣的事情

abstract public class ITTechnician 
{ 
    public abstract void Behavior(); 
    // ... 
} 

public class JonSkeet 
{ 
    public override Behavior() 
    { 
     // Do awesome things 
    } 
} 

,讓上面的代碼可以寫成

ITTechnician itt = GetSomeInstance(); 
itt.Behavior(); 
+1

我相信你也可以在一個抽象類中定義一個默認的構造函數,它的後代自然會調用它。如果後代不調用自定義構造函數,你可以使用這個作爲後備?! – series0ne 2012-08-10 21:31:34

+0

@MatthewLayton:如果你有一個初始化合約,提供一個默認構造函數允許一個子類違反該合約而不是初始化該類型屬性。使用原始的* setup *方法可以獲得相同的效果。一個子類可能會決定不調用* setup *並將該對象置於不正確的初始化狀態。 – 2012-08-10 22:24:07

0

How would I be able to set up a constructor in a way that the abstract class would require it and that I don't have to call technician.setup()

你不需要構建你的邏輯來強制類的行爲,反之亦然。 Abstract類定義了一個必須由孩子跟隨的stuf。

如果您在abstract類,它初始化每當child對象將構造您所需要的變量,一個簡單的parametless構造函數中,abstract默認的構造函數將被調用之前,所以intialization將被執行。

更清楚:

public class Child : Base 
{ 

    public Child(int x){ 
    "Child".Dump(); 
    } 
} 

public abstract class Base 
{ 

    public Base() { 

     //INIT VARIABLES HERE 
     "Base".Dump(); 
    } 
} 

使用這些結構,如

vaar ch = new Child();產生的結果

"Base" 
"Child" 

如果這不是你問什麼,請澄清。

0

要在運行時發現類型,請使用GetType()。沒有必要創建自己的類型字符串字段。

在你的班級結構中唯一不同於內在類型的是IsJonSkeet。我們可以使用.NET屬性來實現這一點,與傳統私有/受保護領域的Getter和Setter相比,這是一種更現代和更具表現力的方式。

abstract public class ITTechnician 
{ 
    public bool IsJonSkeet { get; protected set; } 
    protected ITTechnician() 
    { 
     this.IsJonSkeet = false; 
    } 
} 

public class JonSkeet : ITTechnician 
{ 
    public JonSkeet() 
    { 
     this.IsJonSkeet = true; 
    } 
} 

public class Whisperity : ITTechnician 
{ 
} 

現在你itt_type弦場已被刪除,Whisperity相同的基類,所以沒有必要構造做任何初始化 - 它會自動拿起其父的IsJonSkeet值。

對於Eric J的班級設計提示也是+1。您應該使用層次結構的設計來封裝不同的內容,這會使您的調用代碼更加透明,並且代碼庫將來更容易擴展。