如何扩展与通用参数兼容的接口?

时间:2014-03-24 12:52:35

标签: java generics interface subtyping

跟进this question,但我会尝试让它自成一体。

假设我有一个名为Animal的接口,由于各种原因,它有一个表示实现类的泛型类型参数:

public interface Animal<A extends Animal<A>>

我还有一个子接口Dinosaur,其行为方式相同:

public interface Dinosaur<D extends Dinosaur<D>> extends Animal<D>

现在我有一个实现Lizard的课程Animal

public class Lizard implements Animal<Lizard>

和一个子类Trex,它实现了Dinosaur

public class Trex extends Lizard implements Dinosaur<Trex>

这四个声明现在产生错误。这是因为类Trex实现了两次接口Animal,但具有不同的类型参数:因为它扩展了Lizard,所以它实现了接口Animal<Lizard>,并且因为它实现了{ {1}},它实现了Dinosaur<Trex>

Animal<Trex>不是Animal<Trex>的子接口,即使Animal<Lizard>Trex的子类,因此我们得到编译器错误。

我确定使用通配符可以解决这个问题,但我无法弄清楚它是什么。

您可以编译以获得相同的错误:

Lizard

1 个答案:

答案 0 :(得分:2)

  

这是因为Trex类实现了两次接口Animal,但具有不同的类型参数

是的,情况确实如此,并且没有办法直接解决这个问题 - 这是一个技术限制,因为泛型是使用擦除来实现的。 您永远不能在具有不同通用参数的多个类上实现相同的接口。当擦除泛型类型时,您最终会以相同的方式扩展两个接口,无法区分使用那些不同泛型类型的方法,因此运行时无法确定执行哪种方法。

对于您的特定用例,可能有一种解决方法,这意味着您不必使用不同的类型参数实现相同的界面,但如果没有更多详细信息,则无法说出可能的内容是

编辑:看看链接的问题,看起来你可以通过使用另一个答案(你还没有接受的答案)来解决这个问题,它以这种方式指定返回值,而不是在课堂上声明它:

public <T extends JNumber> T add(T addend);

这应该意味着您不需要在类和接口上声明泛型类型参数,因此不应该有这个问题。