从基类列表中访问派生类的字段

本文关键字:字段 派生 访问 基类 列表 | 更新日期: 2023-09-27 17:57:06

我正在使用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);
    }
}

只把这些方法、字段等放进去,这样我就可以在列表中访问它们被覆盖的版本

所以我被覆盖的版本看起来像这样:奥布洛克.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总是空的...

从基类列表中访问派生类的字段

公共新机构m_body;//这是对的吗?

不!这声明了第二位存储 - 所以你有 Block 的 m_body 和 OBlock 的m_body,你只初始化一个为非空。对m_body的特定引用将解析为什么的确切规则可能太无聊而无法理解。

您可能应该完全删除上面的行,并花一些时间熟悉继承的基础知识,例如 http://msdn.microsoft.com/en-gb/library/ms173149.aspx

public new Body m_body;

这是不对的。Block类中的m_body(您应该将其标记为abstract顺便说一句)在派生它的所有类中都可见。你现在正在做的事情被称为隐藏(imo应该始终避免),这会导致各种并发症。

您现在已经做到了,每个OBlock都有两个成员m_body,一个属于Block,一个属于OBlock。这样,每当您在OBlock类中引用this.m_body时,您都会分配属于OBlockm_body字段,而m_block单独声明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无论如何都会被派生的所有类继承。

public new Body m_body; 

这将隐藏基类m_body。所以基本上你在派生类(不是基类)中定义一个新的m_body实例。所以我假设这就是你的基类m_body为空的原因,因为它永远不会初始化。

因此,请删除该特定行,因为对于每个派生类,m_body都已定义为所有派生自 Block 类。有关更多详细信息,请参阅此 MSDN 文章。