2013-02-03 77 views
0

我使用C#和XNA 4.0以及Farseer Physics Engine(非常類似於Box2D),並且有一個Block類,我從中派生出OBlock,LBlock,等從基類列表中訪問派生類的字段

塊如下:

class Block 
{ 
    public Body m_body; 
    public virtual void Draw(SpriteBatch spriteBatch) { } 

    public virtual void RemoveBody(World world) 
    { 
     //world.RemoveBody(m_body); 
    } 
} 

我只把那些方法,字段等,在這樣我就可以訪問列表的重載版本

所以我重寫的版本看起來像這樣: OBlock.cs

class OBlock : Block 
{ 

    private static Texture2D blockImg; //I load this in LoadContent so I don't have loads of Texture2Ds 
    public new Body m_body; //Is this right? 

    public OBlock(World world, Vector2 position) 
    { 
     m_body = BodyFactory.CreateBody(world, position); // Create the body, changing it from null 
     FixtureFactory.AttachRectangle(Game1.blockSide *2, Game1.blockSide *2, 1.0f, new Vector2(0, 0), m_body); //This bit changes between classes 
     m_body.BodyType = BodyType.Dynamic; 

    } 

    public override void RemoveBody(World world) 
    { 
     world.RemoveBody(m_body); 
    } 

    public static void LoadImage(Texture2D tex) 
    { 
     OBlock.blockImg = tex; 
    } 

    public override void Draw(SpriteBatch spriteBatch) 
    { 

     Vector2 position = m_body.Position * Game1.MetreInPixels; 
     Vector2 origin = new Vector2(blockImg.Width/2, blockImg.Height/2); 

     float rotation = m_body.Rotation; 

     spriteBatch.Begin(); 

     spriteBatch.Draw(blockImg, position, null, Color.White, rotation, origin, Game1.BLOCK_SCALE, SpriteEffects.None, 1); 

     spriteBatch.End(); 

     base.Draw(spriteBatch); 
    } 
} 

還有LBlock,ZBlock等,除了我評論的位之外,它們都非常相似。

我然後讓他們都在

List<Block> blocks //As a field in Game1 

blocks = new List<Block>(); // In LoadContent after loading images 

我試圖做的是列表中的任何塊訪問m_body無論使用

blocks[index].m_body.DOSTUFF(); 

類型顯然m_body總是空。 ...

+0

什麼,當你通過一行代碼一步一個線,看的對象m_body發生什麼呢? – SecurityMatt

回答

0
public new Body m_body; 

這是不對的。從Block類(您應該標記abstract btw)的m_body在從它派生的所有類中都可見。你現在正在做的是被稱爲隱藏(這應該總是避免imo),這會導致各種複雜化。

您現在已經制作了每個OBlock有兩個成員m_body,一個屬於Block,一個屬於OBlock。它使得您在任何時候在OBlock類中參考this.m_body時,都可以指定字段屬於OBlock,而Block僅在Block中聲明m_block。這是一個帶有隱藏成員怪異的併發症之一:

Block myBlock = new OBlock(); 
// myBlock.m_block is null, because myBlock is of type block, and remember, 
// the m_block belonging to Block is never assigned to, only the one belonging 
// to OBlock 

而這會達到預期效果:

OBlock myOBlock = new OBlock(); 
// myOBlock.m_block isn't null, because it was assigned to in the constructor. 

因此要避免藏身!從你的代碼文件中刪除

public new Body m_body; 

,你是好去,因爲在Block宣佈m_block由反正從中獲取的所有類繼承。

+0

的事情是,我想有我所有的不同的塊,我可以一步雖然一個列表,並訪問我想任何塊的屍體。我是對的,這需要一個基類的列表來逐步通過,然後我把派生類放入? –

+0

@WilliamOsborne你循環遍歷列表並用派生類yes來實例化它們中的每一個。如果你從你的代碼中刪除了'public new Body m_body''行,那麼一切都會好起來的,並且可以像你所描述的那樣工作。 – antonijn

+0

啊,是的,它現在有效。謝謝! –

2

public new Body m_body; //這是正確的嗎?

不!這聲明瞭第二個存儲位 - 所以你有Block的m_body和OBlock的m_body,你只能初始化一個非空。關於m_body的特定引用將要解決的確切規則可能太無聊而不想理解。

您應該完全刪除上面的行,並花一些時間來熟悉繼承的基礎知識,例如, http://msdn.microsoft.com/en-gb/library/ms173149.aspx

0
public new Body m_body; 

這隱藏了基類的m_body。所以基本上你是在派生類(而不是基類)中定義一個新的m_body實例。所以我認爲這就是你的基類m_body將爲空的原因,因爲它從不初始化。

所以相反,刪除該特定行,因爲對於每個派生類,m_body已定義爲所有派生自Block類。請通過this MSDN article瞭解更多詳情。