【问题标题】:Accessing member variable in subclass (C#)访问子类中的成员变量(C#)
【发布时间】:2017-09-13 07:31:56
【问题描述】:

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

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 放入基础 Sprite 类时才有效。我假设这是因为编译器想要在游戏正在搜索的每个对象中找到变量。我不确定为什么这是一个问题,因为访问 v2Speed 的代码只应用于 Player 对象,该对象将始终定义该向量。我真的不想在任何高于 MovingObject 类的类中使用 v2Speed,因为 Sprite 和 StaticObject > 游戏开始后物体永远不会移动。

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

【问题讨论】:

标签: c# oop inheritance


【解决方案1】:

编译器只知道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,因为你知道它是一个玩家......)

【讨论】:

  • 非常感谢乔恩!我不太明白为什么在我的原始代码中编译器只知道 gameObject 是 Sprite 类型。我原以为使用 typeof (Player) 的 if 语句会解决这个问题。我一定错过了一些关于它是如何工作的知识!无论如何,您的代码已经解决了我的问题,所以谢谢!
  • @AndyLatham:基本上,变量的编译时类型不会根据你对它的处理而改变。
【解决方案2】:

可以使用 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 的强制转换。

【讨论】:

    【解决方案3】:

    您需要进行类型转换,并且应该使用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));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      相关资源
      最近更新 更多