我正在尝试创建一个方法,该方法获取枚举值并返回一个基于该枚举值强制转换为类的对象。例如,我有一个名为componenttype的枚举:
public enum ComponentType
{
HEALTH(HealthComponent.class),
HUNGER(HungerComponent.class);
private Class extends Component> componentClass;
private ComponentType(Class extends Component> componentClass)
{
this.componentClass = componentClass;
}
public Class extends Component> getComponentClass()
{
return componentClass;
}
}
“healthcomponent”和”hungercomponent”是两个扩展名为”component”的类的类。在这个问题上,他们内心的东西并不重要。
一个实体会有一个被分配的组件列表(例如,一个实体可能饥饿,而另一个实体可能健康,另一个实体可能两者都有)。
我的目标是在实体内部创建一个方法,当传入component type枚举中的值时,将返回一个组件对象,该对象被强制转换为该值的相应类类型。因此,如果传入componenttype.health,该方法将返回一个强制转换为healthcomponent的对象。这是我正在尝试的,但它不起作用:(编辑:见下文)
public T getComponentByType(ComponentType type)
{
Class extends Component> componentClass = type.getComponentClass();
for(Component component : componentList)
{
if(component.getClass() == componentClass)
{
return (T) componentClass.cast(component);
}
}
return null;
}
对于上述方法,当传入componentType.health类型时:
entity.getComponentByType(ComponentType.HEALTH);
将返回强制转换为”component”而不是”healthcomponent”的对象。我希望它返回一个转换为healthcomponent的对象,而不是组件。
有什么办法吗?我觉得这是可能的。我之所以想找到一种方法来做到这一点,是因为它看起来像是在做所有这些演员:
HealthComponent component = (HealthComponent) entity.getComponentByType(ComponentType.HEALTH);
这有点浪费,因为方法可以(希望)假定我希望通过传入的componentType强制转换的内容。
编辑(详细信息):
仔细观察结果,我注意到我的方法在某些方面有效。我的意思是,在Eclipse中,如果我键入:
component = entity.getComponentByType(ComponentType.HEALTH);
(组件变量尚未定义)然后将鼠标悬停在getcomponentByType上,查看返回的内容,它表示返回Component。
但是,如果我手动定义变量类型(大多数时候我只是让Eclipse为我创建变量),如下所示:
HealthComponent component = entity.getComponentByType(ComponentType.HEALTH);
然后将鼠标悬停在getcomponentbytype上,查看它返回的是什么,它说它返回HealthComponent,并且它编译并运行。所以从技术上讲是可行的,但不是按照我希望的方式。这是一个小问题,因为如果我在第一个示例中告诉Eclipse为我创建一个局部变量,它将创建一个类型为”component”的变量,我必须手动更改它。
那么,当您编译和运行代码时会发生什么?
@jbinzet请参见上面的编辑。
它是一个泛型方法,编译器无法通过其参数的类型推断其返回的类型。所以它只能由它分配给的变量的类型来推断。你可以一直使用entity.getComponentByType(ComponentType.HEALTH)。
@好吧,我想那就得这么做了。谢谢!
您似乎将表达式的类型与对象的类混淆了。铸造只影响前者。对类型Component的引用进行计算的表达式可以引用其类是Component的子类型的对象。
不能更改对象的类。并且不能”动态”地将引用从一种类型强制转换为另一种类型。这个话题一周讲一次。
@辣妹,对,对不起。在我的问题中,我可能错误地使用了一些词汇,但我理解您不能更改对象的类。不过,谢谢你提供的另一条信息!我确实尝试过搜索,但找不到任何东西。我也可能没有在搜索中使用正确的词汇。
@约翰博林格感谢你提供的信息!
如果你考虑一下,对一个对象引用进行”动态”转换是没有实际意义的,因为你随后对它的处理受到编译器在编译时的想法的约束。
您希望getComponentByType()的编译时返回类型取决于用于选择组件的参数。对于泛型,这是可能的,但前提是参数实际包含您需要的编译时类型信息。
不幸的是,您不能将类型参数添加到枚举值中(参见本问题),但是如果您再次查看自己的代码,您可能会意识到您已经有了一个对象,该对象恰当地描述了您想要获取的组件,并且正好包含了我们需要的类型信息:每个组件类型的Class<>对象!
所以,这是我对您的功能的建议(没有编译或测试,请注意,我的Java可能生锈):
public T getComponentByType(Class type)
{
for(Component component : componentList)
{
if(component.getClass() == type)
{
return (T)component;
}
}
return null;
}
我想这对我有用,谢谢!
我迟到了4年,但我遇到这个问题是因为我遇到了类似的情况,想要一个好的解决方案。
可以通过给枚举一种提取和强制转换的方法来解决这个问题,而不是依赖一个试图找出类型的实体。
例如,可以向componenttype枚举添加如下方法:
public C fromEntity(Entity entity) {
List componentList = entity.getComponentList();
// add your existing iteration and type casting logic here
}
稍后不再尝试:
HealthComponent component = (HealthComponent) entity.getComponentByType(ComponentType.HEALTH);
你可以写这样的东西
HealthComponent component = ComponentType.HEALTH.fromEntity(entity);
在我的例子中,我希望有一个带有枚举键的映射,并使用如下解决方案:
https://gist.github.com/hiljust/5240d42e827b77e65f41f0a7dfac4406