在子类中访问成员变量(C#)

时间:2017-09-13 07:31:56

标签: c# oop inheritance

我游戏中的所有对象都继承了我的 Sprite 类。这是我正在使用的层次结构:

精灵> StaticObject > MovingObject > 字符>的播放器

我在我的主游戏类中编写了一个函数,用于搜索游戏中的所有对象并找到任何“ Player ”对象。如果找到 Player 对象,它会在屏幕上显示对象速度的值( v2Speed 向量)。

foreach (var gameObject in GameInfo.gameInfo.gameObjects)
{
    if (gameObject.GetType() == typeof (Player))
    {
        string sPlayerPosition = string.Format("Player position: ({0:0.00},{1:0.00})", gameObject.v2Position.X, gameObject.v2Position.Y);
        DrawWithShadow(sPlayerPosition, new Vector2(10, 60));

        string sPlayerSpeed = string.Format("Player speed: ({0:0.00},{1:0.00})", gameObject.v2Speed.X, gameObject.v2Speed.Y);
        DrawWithShadow(sPlayerSpeed, new Vector2(10, 80));
    }
}

但是,只有在基本精灵类中放置 v2Speed 时,才有效。我假设这是因为编译器想要在游戏搜索的每个对象中找到变量。我不确定这是一个问题,因为访问 v2Speed 的代码只会应用于播放器对象,该对象始终会定义该向量。我真的不希望在 MovingObject 类的任何类中都有 v2Speed ,因为 Sprite StaticObject 一旦游戏开始,对象将永远不会移动。

我的问题是,如果它存储在 MovingObject 类而不是 Sprite 类中,如何重写上面的代码来访问 v2Speed

3 个答案:

答案 0 :(得分:4)

编译器只知道gameObject类型为Sprite(我假设;很难确定)。您的if条件不会改变该条件。

相反,您可以使用:

if (gameObject is Player player)
{
    // Now use player instead of gameObject
}

请注意,这需要C#7。如果您只使用C#6或更早版本,则使用:

Player player = gameObject as Player;
if (player != null)
{
    // ...
}

请注意,这与原始代码的行为略有不同 - 如果您的对象是Player子类的实例,则不会在原始代码中拾取它代码,但将在此代码中...这可能是你想要的。

(根据Codor的答案OfType<Player>方法是一个很好的选择 - 虽然我会调用循环变量player而不是gameObject,因为你知道它是一个球员......)

答案 1 :(得分:1)

可以使用Linq更改代码,如下所示。

foreach (var gameObject in GameInfo.gameInfo.gameObjects.OfType<Player>())
{
    string sPlayerPosition
        = string.Format("Player position: ({0:0.00},{1:0.00})", 
                gameObject.v2Position.X, gameObject.v2Position.Y);
                DrawWithShadow(sPlayerPosition, new Vector2(10, 60));

    string sPlayerSpeed
        = string.Format("Player speed: ({0:0.00},{1:0.00})", 
                gameObject.v2Speed.X, gameObject.v2Speed.Y);
                DrawWithShadow(sPlayerSpeed, new Vector2(10, 80));

}

或者,可以在循环体内使用Player的强制转换。

答案 2 :(得分:1)

您需要进行类型转换,并且应该使用as执行此操作,因为您不确定该对象是否属于Player类型。

像这样:

foreach (var gameObject in GameInfo.gameInfo.gameObjects)
{
    var player = gameObject as Player;  // try to do Type Cast
    if (player != null)             // if true, then Type Cast has succeeded
    {
        string sPlayerPosition = string.Format("Player position: ({0:0.00},{1:0.00})", player.v2Position.X, player.v2Position.Y);
        DrawWithShadow(sPlayerPosition, new Vector2(10, 60));

        string sPlayerSpeed = string.Format("Player speed: ({0:0.00},{1:0.00})", player.v2Speed.X, player.v2Speed.Y);
        DrawWithShadow(sPlayerSpeed, new Vector2(10, 80));
    }
}