简体   繁体   English

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

[英]How can I make extensions of interfaces compatible with generic parameters?

Follow up to this question , but I'll try to make it self-contained. 跟进这个问题 ,但我会尽力使它成为独立的。

Suppose I have an interface called Animal , which for various reasons has a generic type parameter representing the implementing class: 假设我有一个名为Animal的接口,由于各种原因,该接口具有一个表示实现类的通用类型参数:

public interface Animal<A extends Animal<A>>

I also have a sub-interface, Dinosaur , which behaves in the same way: 我还有一个子接口Dinosaur ,其行为方式相同:

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

Now I have a class Lizard which implements Animal : 现在我有一个实现Animal Lizard类:

public class Lizard implements Animal<Lizard>

and a subclass, Trex , which implements Dinosaur : 还有一个实现了Dinosaur的子类Trex

public class Trex extends Lizard implements Dinosaur<Trex>

These four declarations now produce an error. 这四个声明现在产生一个错误。 This is because the class Trex implements the interface Animal twice, but with different type parameters: since it extends Lizard , it implements the interface Animal<Lizard> , and since it implements Dinosaur<Trex> , it implements Animal<Trex> . 这是因为Trex类两次实现了Animal接口,但是具有不同的类型参数:由于它扩展了Lizard ,因此实现了接口Animal<Lizard> ,并且由于实现了Dinosaur<Trex> ,因此实现了Animal<Trex>

Animal<Trex> is not a subinterface of Animal<Lizard> , even though Trex is a subclass of Lizard , so we get a compiler error. 即使TrexLizard的子类, Animal<Trex>也不是Animal<Lizard>的子接口,因此我们会遇到编译器错误。

I'm sure there's some way around this using wildcards, but I can't work out what it is. 我确定使用通配符可以解决此问题,但是我无法弄清楚它是什么。

Here's something you can compile to get the same error: 您可以编译以下内容以获得相同的错误:

public class InterfaceTest
{
  private interface Animal<A extends Animal<A>> {}

  private interface Dinosaur<D extends Dinosaur<D>> extends Animal<D> {}

  private class Lizard implements Animal<Lizard> {}

  private class Trex extends Lizard implements Dinosaur<Trex> {}
}

This is because the class Trex implements the interface Animal twice, but with different type parameters 这是因为Trex类两次实现了接口Animal,但是具有不同的类型参数

Yup, this is the case, and there's no way around this directly - it's a technical limitation because generics are implemented using erasure. 是的,确实是这种情况,并且无法直接解决-这是一个技术限制,因为泛型是使用擦除来实现的。 You can never implement the same interface on more than one class with different generic parameters. 您永远不能在具有不同通用参数的多个类上实现同一接口。 When the generic types are erased you'd end up with it extending two interfaces identically, with no way to distinguish between methods making use of those different generic types, and thus no way for the runtime to determine which method to execute. 当泛型类型被删除时,您将最终以相同的方式扩展两个接口,无法区分使用这些不同泛型类型的方法,因此运行时也无法确定执行哪种方法。

For your particular use case there's probably a workaround that means you don't have to implement the same interface with different type parameters, but without more details it's impossible to say what that might be. 对于您的特定用例,可能有一种解决方法,这意味着您不必使用不同的类型参数来实现相同的接口,但是如果没有更多细节,就无法说出可能的含义。

EDIT: Looking at the linked question, it looks like you could solve this problem by using the other answer (the one you haven't accepted) that specifies the return value in this way rather than declaring it on the class: 编辑:查看链接的问题,看起来您可以通过使用以这种方式指定返回值而不是在类中声明返回值的另一个答案(您尚未接受的答案)来解决此问题:

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

This should then mean you don't need to declare the generic type parameter on your classes and interfaces, and then thus shouldn't have this issue. 然后,这应该意味着您不需要在类和接口上声明泛型类型参数,因此也就不会出现此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM