从集合中检索对象时向下转换对象

时间:2016-08-23 20:47:07

标签: java

我目前正在编写一个游戏,使用基于自编写组件的实体引擎的变体。 当我定义我的实体及其所拥有的组件时,我想使用以下想法正确地对它们进行处理以供系统的其余部分使用:

class Entity {

...

用于识别不同的组件:

enum ComponentID() {
    BODY,
    GRAPHICS,
    INVENTORY;
}
...

应该包含所有组件:

EnumMap<ComponentID, ModelComponent> components = new EnumMap<>(ComponentID.class);
}

首先,我们有一个名为ModelComponent的超类和一些不同的具体子类,如Body,Graphics,AI等,它们扩展了ModelComponent。

组件EnumMap应该保存对实体具有的所有ModelComponents的引用。 当我想向系统询问特定组件时,就会出现问题。如果我想获取body组件,例如因为物理类想要计算一些碰撞,我会编写如下代码:

public Body getBody() {
    return (Body) components.get(ComponentID.BODY);
}

需要演员,因为我的游戏中的某个地方,如果我想访问实体的速度,我会调用:

Vector2 velocity = entity.getBody().getVelocity();

但是,getVelocity()是一个仅在具体子类Body中定义的方法。

我的问题是:这是对子类的向下转换的正确用法吗?我不知道,是否可以通过更好的设计来避免向下转换,因为显然一个Graphics组件将完成与Body组件完全不同的东西,所以它们都将具有完全不同的方法。

修改

我忘了提及以下可能对回答这个问题很重要的细节:

1)当然,还有更多具体的实体子类,如Player,Enemy,Trigger等,它们都应该具有不同的ModelComponents组合。 玩家不需要像敌人那样的AI组件。

2)我对这个重构的目标是摆脱字段

Body body;
Graphics graphics;
Inventory inventory;
Ai ai;

因为在我的游戏中实例化的每个实体都会拥有所有这些字段。 enummap可以消除这个问题,因为我将使用以下代码行替换所有getXXX()方法:

public ModelComponent get(ComponentID id) {
return components.get(id);

}

1 个答案:

答案 0 :(得分:1)

简短的回答是:不。因为您正在添加隐含逻辑。在这种情况下,向下转换是有效的,因为你知道它是正确的,因为在代码中你将设置正确的对象。但编译器无法检查这一点,也可能无法检查其他开发人员。所以其他人可以更改代码,编译器不会抱怨,只有在运行时才会抛出类转换异常。