设计:在超类中的字段的子类中引用

时间:2009-10-29 18:34:34

标签: oop

首先,我不知道标题是否反映了我的问题。如果你有更好的主意,我道歉并请求改变它。

现在,我遇到的问题主要是设计问题。我不确定我想要的是一个好的做法,但它很方便。

我有一个名为 IMovement 的界面。

两个类实现 IMovement VelocityMovement SplineMovement

我还有一个名为精灵的课程。 Sprite有一个 IMovement

最后,我有两个Sprite的子级:玩家敌人

知道 播放器始终 VelocityMovement
知道 敌人 始终 SplineMovement

除了超级类引用IMovement之外,还有一个属于VelocityMovement或SplineMovement分别来自Player或Enemy的错误(无论是设计还是实际)?

换句话说:

Interface IMovement {
  public Vector2 getPosition(int time);
}

class VeloctiyMovement implements IMovement { 
   public Vector2 velocity;

   public Vector2 getPosition(int time) { ... }
}

class SplineMovement implements IMovement { 
   public Spline spline;

   public Vector2 getPosition(int time) { ... }
}

class Sprite {
  IMovement movement;
}

class Player extends Sprite {
  public VelocityMovement velocityMovement;

  public Player() {
    velocityMovement = new VelocityMovement();
    movement = velocityMovement;
  }
}

class Enemy extends Sprite {
  public SplineMovement splineMovement;

  public Enemy() {
    splineMovement = new SplineMovement();
    movement = splineMovement();
  }
}

我想在子类中使用引用的原因是方便。有一半次我需要玩家的速度场,有一半我不在乎。这种情况发生在游戏中,该方法每秒被调用大约100次。

我指出100次的原因是因为我也担心铸造是否昂贵。

示例,而不是:

// When I need the velocity
Vector2 velocity = ((VelocityMovement)player.movement).velocity;
...

// When I don't care
Vector2 position = player.movement.GetPosition(time);
...

我现在可以这样做:

Vector2 velocity = player.VelocityMovement.velocity;
...

Vector2 position = player.movement.GetPosition(time);
...

所以我的问题是:玩家是否有VelocityMovement字段而敌人有SplineMovement?或者这是一个糟糕的设计?

我想你的想法。

更新

我现在记得为什么我选择使用字段IMovement而不是使用Sprite实现IMovement(正如JacobM正确建议的那样)。

这是因为在某些情况下,Enemy可以拥有SplineMovement,而在其他情况下可以使用VelocityMovement。

虽然我错误地说“我知道敌人总是会有SplineMovement”,但我应该说,我知道敌人有VelocityMovement,我会用VelocityMovements聚集所有敌人。我希望你理解我(否则我觉得自己像个白痴)。

例如:

List<Enemy> enemies = GetAllVelocityMovementEnemies();

我这样做是因为在我的游戏逻辑中的某个地方,我想只影响拥有VelocityMovements的敌人群。

所以,虽然JacobM的答案完全有效,但这不适合我的情况。否则,我必须将Enemy与EnemyVelocityMovement和EnemySplineMovement一起继承,依此类推。

所以,对于误解,我已经确定Brian Agnew's答案是我设计中最好的答案。

哦,是的,关于铸造的警告确实是过早的优化。 ;)

2 个答案:

答案 0 :(得分:3)

暂时不要担心优化问题。过早的优化会让你感到悲伤,这很可能是不合理的。

所以,为了回答你的问题,不要在整个层次结构中复制字段 - 这是一个维护问题,你的时间节省可以忽略不计。如果您按照DRY principle进行操作,那么您将免除很多麻烦。

让你的课程通过以下方式移动(比如说):

player.move()

否则(正如你发现的那样),你必须找到他们的IMovement,然后施放它,然后问速度,这真的打破了封装。您的玩家/敌人类可能会有不同的move()实施,具体取决于他们的具体情况。

您可能不需要move()方法,但我想要证明的是,智能包含在类,而不是在调用代码中。因此,您根本不必公开IMovement个对象。

最后,我只会在让它工作后进行优化,测量它以确定您有问题!

答案 1 :(得分:2)

我没有时间尝试编写代码,但是,如果您使用的语言支持泛型类型,则可以执行类似

的操作
class Sprite<T extends IMovement> {
   T movement;
}

class Player extends Sprite<VelocityMovement> {
}

class Enemy extends Sprite<SplineMovement>{
}

这样,当你要求玩家的移动物体时,你已经知道它是一个VelocityMovement(当然你也可以将它称为移动物)。