Oop 设计:在超类中字段的子类中具有引用
首先,我不知道这个标题是否反映了我的问题。我很抱歉,如果你有更好的想法,我恳请你改变它 现在,我的问题主要是一个设计问题。我不确定我想要的是不是一个好的练习,但这很方便 我有一个名为IMovement的界面 两个类实现了IMovement:VelocityMovement,SplineMovement 我还有一个名为“精灵”的类。一个精灵有一个i动作 最后,我有两个子类精灵:玩家和敌人 我知道玩家将始终拥有速度移动和Oop 设计:在超类中字段的子类中具有引用,oop,Oop,首先,我不知道这个标题是否反映了我的问题。我很抱歉,如果你有更好的想法,我恳请你改变它 现在,我的问题主要是一个设计问题。我不确定我想要的是不是一个好的练习,但这很方便 我有一个名为IMovement的界面 两个类实现了IMovement:VelocityMovement,SplineMovement 我还有一个名为“精灵”的类。一个精灵有一个i动作 最后,我有两个子类精灵:玩家和敌人 我知道玩家将始终拥有速度移动和 我知道敌人将永远有夹板移动 除了超类对IMovement的引用之外,将Velo
我知道敌人将永远有夹板移动 除了超类对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。谢谢你们两位。;)我也同意封装,我投票支持你,布莱恩。但我认为泛型在这里也会增加价值,因此值得投入其中。