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

Oop 设计:在超类中字段的子类中具有引用,oop,Oop,首先,我不知道这个标题是否反映了我的问题。我很抱歉,如果你有更好的想法,我恳请你改变它 现在,我的问题主要是一个设计问题。我不确定我想要的是不是一个好的练习,但这很方便 我有一个名为IMovement的界面 两个类实现了IMovement:VelocityMovement,SplineMovement 我还有一个名为“精灵”的类。一个精灵有一个i动作 最后,我有两个子类精灵:玩家和敌人 我知道玩家将始终拥有速度移动和 我知道敌人将永远有夹板移动 除了超类对IMovement的引用之外,将Velo

首先,我不知道这个标题是否反映了我的问题。我很抱歉,如果你有更好的想法,我恳请你改变它

现在,我的问题主要是一个设计问题。我不确定我想要的是不是一个好的练习,但这很方便

我有一个名为IMovement的界面

两个类实现了IMovementVelocityMovementSplineMovement

我还有一个名为“精灵”的类。一个精灵有一个i动作

最后,我有两个子类精灵:玩家敌人

知道玩家始终拥有速度移动
知道敌人永远夹板移动

除了超类对IMovement的引用之外,将VelocityMovement或SplineMovement的属性分别指定给玩家或敌人,这是错误的(无论是设计还是实际的)吗

换言之:

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);
...
所以我的问题是:玩家应该有一个速度运动场,而敌人应该有一个夹板运动场吗?或者这是一个糟糕的设计

我想听听你的想法

更新

现在我想起了为什么我选择了场IMovement而不是Sprite实现IMovement(正如正确建议的那样)

这是因为在某些情况下,敌人可能有分裂运动,而在另一些情况下,敌人可能有快速运动

虽然我说得不对,“我知道敌人总是有夹板运动”,但我应该说,我知道敌人在我用速度运动聚集所有敌人的地方有速度运动。我希望你能理解我(否则我会觉得自己像个白痴)

例如:

List<Enemy> enemies = GetAllVelocityMovementEnemies();
<代码>列出敌人=GetAllVelocityMovementOblues(); 我这样做是因为在我的游戏逻辑中,我只想影响那些有速度运动的敌人

因此,尽管雅各布的答案作为一种设计是完全正确的,但这并不适用于我的情况。否则,我将不得不用EnemyVelocityMovement和EnemySplinMovement等子类化敌人

所以,很抱歉误解,我已经决定答案是我的设计最好的一个


哦,是的,对铸造的警惕确实是过早的

暂时不要担心优化。过早的优化会给你带来不必要的悲伤

因此,为了回答您的问题,不要在整个层次结构中重复字段-这是一个维护难题,而且您感觉到的节省时间可以忽略不计。如果你遵循这个原则,那么你会省去很多麻烦

让你的班级通过以下方式移动(比如):

player.move()
否则(正如您所发现的),您必须找到他们的
IMovement
,然后对其进行强制转换,然后要求其提供速度,这确实破坏了封装。你的玩家/敌人职业可能会有不同的
move()
实现,这取决于他们的具体情况

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


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

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

class Sprite<T extends IMovement> {
   T movement;
}

class Player extends Sprite<VelocityMovement> {
}

class Enemy extends Sprite<SplineMovement>{
}
类精灵{
T运动;
}
类播放器扩展了精灵{
}
类敌人扩展精灵{
}

这样,当你询问玩家的移动对象时,你已经知道这是一个速度移动(当然你也可以将其称为IMovement)。

我更新了我的问题。玩家/敌人确实有一个基类:精灵。它确实包含了一种运动。我的问题是,如果玩家/敌人除了从Sprite继承的IMovement之外,还应该有一个VelocityMovement/SplinMovement。注意:VelocityMovement/SplinMovement与基类SpriteAlso中的IMovement引用相同,getVelocity只适用于VelocityMovement,而不适用于IMovement(因为SplineMovement没有速度)。因此getVelocity()不能在sprite中,而是在Player中。如果您根据语言对此进行标记,可能会有所帮助。虽然我主要关心设计,但如果有帮助的话,它是C#(但也可以是Java)好主意!从来没有想到过!我仍然认为真正的问题是封装,对象本身应该注意它们的运动。我完全同意封装问题。所以我会让Sprite扩展IMovement,而VelocityMovement会有setVelocity。谢谢你们两位。;)我也同意封装,我投票支持你,布莱恩。但我认为泛型在这里也会增加价值,因此值得投入其中。