我目前正在开发一个轻量级的通用模拟框架。目标是允许人们根据他们特定领域的需求对模拟和场景对象进行子类化。泛型似乎是实现这一目标的合适方式,但我担心我可能会陷入泛型 hell 。
Sim
对象提供对模拟实体的访问并控制模拟(开始/暂停/停止)
Scenario
对象允许您使用模拟实体填充 Sim。
西姆:
public class Sim
{
public <T extends Sim> void loadScenario(Scenario<T> scenario)
{
reset();
scenario.load(this);
}
}
场景:
public interface Scenario<T extends Sim>
{
public void load(T sim);
}
目标是让用户创建一个MySim
那extends Sim
和一个 MyScenario
那implements Scenario<MySim>
对于他们的域。
例如我的场景:
public class MyScenario<MySim>
{
public void load(MySim sim)
{
// make calls to sim.addMySimEntity(...)
}
}
具体来说,使用上面的代码,scenario.load(this)
来电Sim.loadScenario
给我错误:类型 Scenario 中的方法 load(T) 不适用于参数 (Sim)。我明白这是因为我正在加载 this
(类型为 Sim
)当需要的是 T extends Sim
时这意味着我应该以某种方式传递一个对象,该对象可以是 Sim 的任何子类型。
纠正这个问题的方法是什么,以达到我想要完成的目标?或者,这有可能吗?也许泛型不能为我做这件事。
最佳答案
如果它始终是 Sim 的子类型,那么为什么不在您的方法中指定它并完成它呢?在这里,泛型似乎不太适合您。
但无论如何,我认为您希望 loadScenario
为:
public void loadScenario(Scenario<? extends Sim> scenario)
编辑: 好吧,现在我真的想到了,那也行不通。您的 loadScenario 将传递一个带有类型参数 T 的场景,该参数 T 是 Sim 的子类型。但是您正试图将一个 Sim 传递给它,而这个 Sim 不能保证是 Sim 的正确子类型。
解决方法是Scenario.load方法需要取一个Sim viz:
public interface Scenario<T extends Sim>
{
public void load(Sim sim);
}
并且 Sim 保持您编写的方式。请注意,您的 MySim 类必须实现它并将其明确地窄播到它的类型参数。
编辑:另一种方法是在您的 Sim 基类中使用静态方法:
public class Sim
{
public static <T extends Sim> void loadScenario(Scenario<T> scenario, T sim)
{
scenario.load(sim);
}
}
但是不可能使它成为实例方法,因为将 Sim 的实例传递给 T extends Sim 类型的东西不是类型安全的。通过制作一个也传递 Sim 的静态方法,您可以让编译器有机会检查 T for Scenario 类型参数和 T for sim 是否匹配。
关于Java Generics Hell - 传入这个但它想要类型 T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2676153/