我目前正在开发一个轻量级的通用仿真框架.目标是允许人们将Simulation和Scenario对象子类化为其特定于域的需求.仿制药似乎是实现这一目标的合适方式,但我担心我可能会陷入仿制药的地狱.
该Sim对象提供对模拟实体的访问并控制sim(开始/暂停/停止)
该Scenario对象允许您使用模拟实体填充Sim.
SIM卡:
public class Sim
{
public <T extends Sim> void loadScenario(Scenario<T> scenario)
{
reset();
scenario.load(this);
}
}
Run Code Online (Sandbox Code Playgroud)
场景:
public interface Scenario<T extends Sim>
{
public void load(T sim);
}
Run Code Online (Sandbox Code Playgroud)
我们的目标是让用户创建一个MySim是extends Sim和MyScenario这implements Scenario<MySim>对他们的域.
例如MyScenario:
public class MyScenario<MySim>
{
public void load(MySim sim)
{
// make calls to sim.addMySimEntity(...)
}
}
Run Code Online (Sandbox Code Playgroud)
具体来说,使用上面的代码,scenario.load(this)调用Sim.loadScenario给出了错误:Scenario类型中的方法load(T)不适用于参数(Sim).我理解这是因为我正在加载this(这是类型Sim)当需要的是T extends Sim什么意味着我应该传递一个可以是Sim的任何子类型的对象.
有什么方法可以纠正这个问题来实现我想要实现的目标?或者,它甚至可能吗?也许仿制药不能为我做这件事.
如果它总是成为Sim的子类型,那么为什么不在你的方法中指定它并完成呢?似乎仿制药在这里买不到你.
但无论如何,我认为你想loadScenario成为:
public void loadScenario(Scenario<? extends Sim> scenario)
Run Code Online (Sandbox Code Playgroud)
编辑:好的,现在我实际上想过它,这也无济于事.您的loadScenario将通过一个带有类型参数T的场景,该类型参数为Sim的子类型.但是你试图传递一个Sim,它不能保证成为Sim的正确子类型.
解决方案是Scenario.load方法需要采用Sim viz:
public interface Scenario<T extends Sim>
{
public void load(Sim sim);
}
Run Code Online (Sandbox Code Playgroud)
和Sim保持你写它的方式.请注意,您的MySim类必须实现此功能,并明确地将其窄化为类型参数.
编辑:另一种方法是在Sim基类中使用静态方法:
public class Sim
{
public static <T extends Sim> void loadScenario(Scenario<T> scenario, T sim)
{
scenario.load(sim);
}
}
Run Code Online (Sandbox Code Playgroud)
然而,由于将Sim的实例传递给类型为T的类型,因此不能将其作为实例方法,因为Sim不是类型安全的.通过创建一个也通过Sim的静态方法,您可以让编译器有机会检查T for Scenario类型参数和T for sim匹配.
| 归档时间: |
|
| 查看次数: |
568 次 |
| 最近记录: |