我在游戏中实现继承权时遇到了一些麻烦。我认为最好引入继承,因为它会使我的代码更整洁,并以合理的方式组织。
我面临的问题是在从派生类的基类调用构造函数时使用参数。
我使用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)
在玩家类......
//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)
答案 0 :(得分: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()
函数(不可覆盖),该函数接受构造函数所做的所有参数,并在实例化后让拥有类调用它。无论哪种方式,你必须最终给班级所有的信息。
如果我能澄清任何内容或进一步帮助,请告诉我。
<强>更新强>
是的,:base(...)
语法实际上与写入相同(如果它是有效的C#)myBaseClassPointer = new base(...);
(在这种情况下base是Paddle)。同样,这不是有效的C#。实际上,您必须使用:base在使用非默认构造函数时实例化基类。它设置属性的方式与直接实例化它的方式相同,只要它们没有标记为私有,它们就可以从派生类中获得(子是有点用词不当,因为该术语通常指的是组合)。
我建议不要使用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
。
答案 1 :(得分:0)
由于paddle对象具有Player
和Enemy
共享的属性,因此组合是比继承更好的选择。 (通过继承,你不能破坏基础对象,因为该对象为每个对象构造独立)实现涉及构建(共享)Paddle
,然后将其传递给Player
和{{1}的c-tor }}
我不确定为什么Enemy
属性如位置和速度被共享。 Paddle
似乎是唯一应该共享的属性。如果这是像Pong之类的游戏,则每个玩家都有自己的位置和速度,但两者都是在同一个GUI组件上绘制的。如果是这种情况,Player和Enemy都是paddles并且inheritnace很好,但ViewPort则是共享的。实施涉及构建ViewPort
并将其与ViewPort
(或Player
)的位置,速度等一起传递给Enemy
(或{{1}然后将c-tor传递给基础Player
c-tor