【问题标题】:Unsure about parameters when calling base constructor from derived class从派生类调用基构造函数时不确定参数
【发布时间】:2014-04-11 16:28:00
【问题描述】:

在我的游戏中实现继承时遇到了一些麻烦。我认为最好引入继承,因为它会使我的代码更整洁,更有条理。

我在atm面临的问题是从派生类中的基类调用构造函数时的参数。

我使用 Paddle 类作为基类,Player 类作为继承 Paddle 的类。

代码如下:

在 Paddle 类中......

//properties

  protected Texture2D pTexture;
  protected Vector2 pPosition;
  protected Vector2 pVelocity;


//constructor for Paddle class (only first line here, as the rest is irrelevant)

public Paddle(Texture2D newTexture, Vector2 newPosition, Viewport theViewport, Color newColour)

在 Player 类中......

//properties
PlayerIndex pID;


//constructor for Player class (only first line here, as the rest is irrelevant)
public Player(PlayerIndex newID) : base()

在你提到它不工作的原因之前,因为我在 Player 类中调用的基构造函数没有任何参数,而基类/Paddle 类中的构造函数有,我理解这一点。我面临的问题是设置播放器的纹理、位置等,但纹理、位置等在基类中,因为它们是 Player 和 Enemy 类的通用属性(另一个继承自 Paddle 的类,但它是相似的给玩家,因此现在只提到它)。在 Player 类中调用基构造函数时,我也不知道该放什么作为参数。

感谢您的阅读和提前帮助:-)

添加的代码我已更改如下:

public Player(PlayerIndex newID, Texture2D newTexture, Vector2 newPosition, Viewport theViewport, Color newColour)
        : base(newTexture, newPosition, theViewport, newColour)

【问题讨论】:

  • 如果您不确定,那么我相信您的继承结构有误。您当前的代码是说玩家类将具有 Paddle 类的所有属性,但看起来并非如此。
  • 有什么问题?你知道为什么它不起作用。那么为什么不直接传递所需的参数来使其工作呢?

标签: c# class inheritance constructor xna


【解决方案1】:

要以这种方式使用构造函数,您必须向派生构造函数提供基构造函数所需的所有信息,以便它可以像这样调用它:

public Player(PlayerIndex newID, Texture2D newTexture, Vector2 newPosition, Viewport theViewport, Color newColour)

然后你传递到基地:

public Player(PlayerIndex newID, Texture2D newTexture, Vector2 newPosition, Viewport theViewport, Color newColour) : base(newTexture, newPosition, theViewport, newColour);

显然,这使得 Player 构造函数变得相当大。为避免此问题,您可以在基类(不可覆盖)上声明一个 Init() 函数,该函数接受构造函数所做的所有参数,并让所属类在实例化后调用它。无论哪种方式,您最终都必须向班级提供所有信息。

如果我可以澄清任何事情或提供进一步帮助,请告诉我!

更新

  1. 是的,:base(...) 语法实际上与编写(如果它是有效的 C#)myBaseClassPointer = new base(...);(在这种情况下,base 是 Paddle)相同。同样,这不是有效的 C#。使用非默认构造函数时,您实际上必须使用 :base 来实例化基类。它设置属性的方式与您直接实例化它的方式相同,只要它们没有标记为私有,它们就可以从派生类中使用(child 有点用词不当,因为该术语通常指的是组合)。

  2. 我不推荐使用Init() 函数,因为不能保证使用类会调用它。话虽如此,它可以像这样很好地工作:

    class Player
    {
       private bool initialized = false;
       public Player()
       {}
    
       public void Init(Texture2D newTexture, Vector2 newPosition, Viewport theViewport, Color newColour)
       {
          //All the stuff your constructor used to do
          initialized = true;
       }
    
       public void SomeFunctionUsingVariables()
       {
       if (initialized)
       { //Do whatever }
       }
    }
    

唯一的好处是您不必将 Init() 所需的所有数据传递给 Player 构造函数,因此这些字段的知识不需要存在于 Player 类本身中。只要额外的 if 检查没问题并且你记得在实例化类中调用Init,它就可以工作。

【讨论】:

  • 感谢您的回答。我已经添加了一些代码(在上面这个线程的问题部分的末尾),这就是你在这里所说的,尽管它略有不同。我不明白的是,如果我在从 Player 类调用基类时将 newTexture 等作为参数传递,该参数指的是什么?这是否意味着该参数将在 Paddle/基类中使用并修改基类中的属性,然后我可以从子类中调用?谢谢
  • 我真的不明白你关于创建一个 Init() 函数的意思......我的意思是如果你能解释得更详细一点,我希望我能很快理解它,就像我一样相当熟悉使用这样的东西......非常感谢v
  • 更新有所帮助,因为我知道从那里调用基构造函数时使用的派生类构造函数中的参数与直接从基类操作属性相同......非常感谢 v 的帮助!如果我遇到任何其他问题或相关问题,我会进行一些更改并让您知道,所以我会保持这个线程/问题开放一段时间,如果没有问题,我会投票等等......再次感谢! :D
  • 好的,所以我已经将方法等从 Paddle 类移到了 Player 类中......这仅与 Player 相关。唯一的问题 atm 是玩家没有立即被吸引......谢谢
  • 太棒了!只是确保,你没有问一个额外的问题,对吗?我不想不小心忽略它!
【解决方案2】:

由于 paddle 对象具有PlayerEnemy 共享的属性,因此组合是比继承更好的选择。 (通过继承,您不能分享基础对象,因为该对象是为每个对象独立构造的)实现涉及构造一个(共享的)Paddle,然后将其传递给PlayerEnemy 的c-tor。

我不知道为什么Paddle 位置和速度等属性是共享的。 ViewPort 似乎是唯一应该共享的属性。如果这是 Pong 之类的游戏,每个玩家都有自己的位置和速度,但两者都绘制在同一个 GUI 组件上。如果是这样的话,Player 和 Enemy 都是 paddles 并且继承很好,但是 ViewPort 是共享的。实现包括构造一个ViewPort 并将它与Player(或Enemy)的位置、速度等一起传递给Player(或Enemy)c-tor,然后它将通过他们到基地Paddle c-tor

【讨论】:

  • 如果我没看错,他并没有试图共享桨(他显然需要不同的位置,可能需要不同的纹理等)。玩家是桨的“类型”吗?也许,也许不是。根据每个类的多态行为,可以在任一方向进行参数。我实际上倾向于在这里继承(当然没有看到任何其余代码)。
  • 感谢您的回答。基本上我将 Player 和 Enemy 视为 Paddle 的一种,因为我之前只有一个 Paddle 类,但仅用于玩家......但名称可以改进,因此创建了玩家类。我将有一个有自己的位置、纹理等的玩家和一个有自己的位置等的敌人……但他们有共同点,即他们都有一个位置、纹理等,我一直保留在桨类中。
猜你喜欢
  • 2011-05-03
  • 2016-07-19
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-18
  • 2018-07-16
  • 2011-09-27
  • 2019-04-19
相关资源
最近更新 更多