2013-01-16 67 views
4

我對C#有點新,但是在編程方面我有相當廣泛的背景。C#成員變量繼承

我在做什麼:爲遊戲定義不同的MapTiles。我定義的基本MapTile類是這樣的:

public class MapTile 
{ 
    public Texture2D texture; 
    public Rectangle mapRectangle; 

    public MapTile(Rectangle rectangle) 
    { 
     this.mapRectangle = rectangle; 
    } 
} 

我再定義一個子類GrassTile這樣的:

class GrassTile : MapTile 
{ 
    new Texture2D texture = Main.GrassTileTexture; 
    new public Rectangle mapRectangle; 

    public GrassTile(Rectangle rectangle) : base(rectangle) 
    { 
     this.mapRectangle = rectangle; 
    } 
} 

在我的主類我創建這樣一個新的maptile:

Maptile testTile; 
testTile = new GrassTile(new Rectangle(0, 0, 50, 50); 

但是,當我嘗試渲染此testTile時,其紋理結束爲空。如果我在MapTile中定義紋理,我的代碼工作正常,所以它與我以前的實現無關。

那麼我該如何讓GrassTile能夠修改MapTile的成員變量紋理?或者讓我的主類識別GrassTile的紋理,而不是MapTile的我也使用接口,但我無法聲明接口成員變量。有沒有其他的C#繼承,我還沒有得到?

在此先感謝

+0

您能否澄清對Main.GrassTileTexture的引用?這是一個靜態屬性? – jake

+0

對不起,它的靜態屬性在分配給MapTile時正常工作,而不是GrassTile。 – Logicon211

回答

7

子類將繼承父類的成員。你不需要指定它們。此外,最好使用屬性而不是公共字段。

public class MapTile 
{ 
    public Texture2D Texture { get; set; } 
    public Rectangle MapRectangle { get; set; } 

    public MapTile(Rectangle rectangle) 
    { 
     MapRectangle = rectangle; 
    } 
} 

public class GrassTile : MapTile 
{  
    public GrassTile(Rectangle rectangle) : base(rectangle) 
    { 
     Texture = Main.GrassTileTexture; 
    } 
} 
+0

謝謝,這對我有用。快速的問題,財產是不是我可以在C#中定義的東西,我試過「財產」和「公共財產」,沒有顯示任何東西。 另外,那些{get;組; }塊沒有必要,它們是幹什麼用的? – Logicon211

+0

@ Logicon211屬性在C#中有特定的語法,您可以在[msdn about properties](http://msdn.microsoft.com/zh-cn/library/x9fsa0sw.aspx)上閱讀。另外'{get;組; }'block是[自動實現的屬性定義](http://msdn.microsoft.com/en-us/library/bb384054.aspx)的一部分。我認爲這將是非常有用的你閱讀[公共領域和屬性之間的區別](http://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-淨-3-5)。對不起沒有反應 - 是AFK。 –

2

你有一個語法混亂的一點點。 「new」關鍵字既可以用作操作符來實例化某些內容,就像在主要內容中一樣,或者作爲成員的修飾符來隱藏繼承的成員,這就是您在GrassTile中執行的操作。你基本上是在那裏重新定義你的成員。正確的版本可能是:

class GrassTile : MapTile 
    { 
     public GrassTile(Rectangle rectangle) : base(rectangle) 
     { 
      texture = Main.GrassTileTexture; 
     } 
    } 

因爲你的矩形在基礎構造函數中被設置。

+0

閱讀更多在http://msdn.microsoft.com/en-us/library/6fawty39(v=vs.80).aspx – canahari

+0

另一件事是,你不應該使用這樣的靜態變量。 C#被認爲是純粹的面向對象,而我的面向對象的感覺說,即使你絕對必須使用一個靜態變量,你應該在它邏輯上屬於的類中去做。在這種情況下,我會說它應該是MapTile.GrassTexture或GrassTile.Texture – canahari

0

繼承使繼承的字段在派生類中保留。

public sealed class GrassTile : MapTile 
{ 
    public GrassTile(Rectangle rectangle) : base(rectangle) 
    { 
     texture = Main.GrassTileTexture; 
    } 
} 
0

我認爲這是最好的在這裏澄清你如何使用new關鍵字。 new可用於兩種時尚。作爲運營商和修改者。

new

new運算符用於創建對象和調用構造函數 「經營者」,例如:

Class1 MyClass = new Class1(); 

new修改

使用new修飾符顯式隱藏成員繼承來自基類。要隱藏繼承的成員,請使用相同名稱在派生類中聲明它,然後使用新修飾符對其進行修改。

考慮下面的類:

public class MyBaseC 
{ 
    public int x; 
    public void Invoke() {} 
} 

在派生類聲明的名稱調用成員將隱藏方法Invoke在基類,即:

public class MyDerivedC : MyBaseC 
{ 
    new public void Invoke() {} 
} 

然而,字段x不會受到影響,因爲它沒有被類似名稱隱藏。

名稱通過繼承隱藏採用下列形式之一:

  • 的常量,字段,屬性或類型在引入類或結構隱藏所有基類成員具有相同的名稱。

  • 在類或結構中引入的方法在基類中隱藏了具有相同名稱的屬性,字段和類型。它還隱藏了所有具有相同簽名的基類方法。

  • 在類或結構中引入的索引器會隱藏具有相同簽名的所有基類索引器。

既然你的名字隱藏和聲明Maptile類型,但初始化爲孩子GrassTile類型和父MapTile型從未初始化,您Texture成員就是爲什麼你看到null的原因。

0

在代碼中需要改進的幾件事;

首先,屬性Texture已經在基類MapTile中定義了,所以不需要在類GrassTile中重新定義;派生類(GrassTile)從基類(MapTile)繼承此成員。接下來,您可能會考慮將基類'MapTile'修改爲abstract,因爲我認爲它本身沒有直接行爲(紋理必須由具體的dervied類實現提供)。

然後,您可以將texture的聲明修改爲protected,因爲它不應該以這種方式真正在類層次結構外訪問。否則,將其轉變爲getset訪問者的財產。

最後,您使用new修飾符不正確。此修飾符僅用於(在此上下文中)以允許您用新行爲(而不是繼承基本行爲)覆蓋某些行爲的基本實現。在這種情況下,你在GrassTile中聲明瞭一個'new'紋理,這是不必要的,它將覆蓋基本實例,但只有在通過GrassTile類引用時。

{ 
    MapTile m1 = new GrassTile(...); 
    //m1.texture == null; 
    GrassTile m2 = new GrassTile(...); 
    //m2.texture = Main.GrassTileTexture 
}