Java Generics Hell - 传递这个,但它想要类型T

时间:2010-04-20 14:57:18

标签: java generics

我目前正在开发一个轻量级的通用仿真框架。目标是允许人们将Simulation和Scenario对象子类化为其特定于域的需求。泛型似乎是实现这一目标的合适方式,但我担心我可能会陷入泛滥地狱。

Sim对象提供对模拟实体的访问并控制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>

e.g。 MyScenario:

public class MyScenario<MySim>
{
    public void load(MySim sim)
    {
        // make calls to sim.addMySimEntity(...)
    }
}

具体来说,使用上面的代码,scenario.load(this)中的Sim.loadScenario调用给出了错误:方案类型中的方法加载(T)不适用于参数(Sim) 即可。我理解这是因为我正在加载this(类型为Sim),当需要的是T extends Sim时,这意味着我应该传递一个可以是任何Sim 的子类型。

纠正这个问题以实现我想要实现的目标的方法是什么?或者,它甚至可能吗?也许仿制药不能为我做这件事。

2 个答案:

答案 0 :(得分:6)

如果它总是成为Sim的子类型,那么为什么不在你的方法中指定它并完成呢?看起来仿制药在这里买不到你。

但无论如何,我认为你希望loadScenario成为:

public void loadScenario(Scenario<? extends Sim> scenario)

编辑:好的,现在我实际上已经考虑过了,这也无济于事。您的loadScenario将通过一个带有类型参数T的场景,该类型参数为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的类型,因此无法使其成为实例方法,因此Sim不是类型安全的。通过创建一个也通过Sim的静态方法,您可以让编译器检查T for Scenario类型参数和T for sim匹配。

答案 1 :(得分:2)

  

我明白这是因为我   加载此(Sim类型)   当需要的是T延伸Sim   这意味着我应该以某种方式   传入一个可以是任何物体的物体   Sim的子类型。

没有。问题是根据方法规范,你应该传递一个类T的对象,它是与你的场景匹配的Sim的特定子类 - {{1不是(至少那段代码不能保证它是)。

不知道如何解决这个问题。