1

当我试图专门化一个实现泛型接口的类时遇到了一个问题,我想从与超类相同的接口继承,但具有更具体的类型参数。以下代码段显示了一个无法编译的合成但完整的示例。注释包含来自 Java 编译器的错误消息。

interface Producer<T> {
    T get();
}

class NumberProducer implements Producer<Number> {
    @Override
    public Number get() { return null; }
}

// Producer cannot be inherited with different arguments: <java.lang.Integer> and <java.lang.Number>
class IntegerProducer extends NumberProducer implements Producer<Integer> {
    @Override
    public Integer get() { return null; }
}

PECS的意义上,Producer<T>生产者,所以Producer<Integer> 的子类型Producer<Number>,但是没有办法在 的定义中声明它Producer<T>。Java 不允许IntegerProducer同时继承自NumberProducerProducer<Integer>同时继承自并同时IntegerProducer继承。Producer<Integer>Producer<Number>

是否有解决此限制的标准方法,例如解决相同问题而不需要这种继承的模式?

4

3 回答 3

2

只需在超类中添加一个参数:

interface Producer<T> {
    T get();
}

class NumberProducer<T extends Number> implements Producer<T> {
    @Override
    public T get() { return null; }
}

class IntegerProducer extends NumberProducer<Integer> { // Implicit: implements Producer<Integer>
    @Override
    public Integer get() { return null; }
}
于 2013-05-07T12:29:06.067 回答
1

假设我们有一个简单的 Method gimme

public static <T> T gimme(Producer<T> p) { return p.get(); }

gimme什么都不知道的情况下T。它可以是NumberInteger或任何其他引用类型。因此,由于擦除,编译器会发出对的接口调用,Producer.get()Object而不是对IntegerProducer.get()Integer. 所有实现Producer<T>with 的类型T != Object也隐式实现Producer.get()Object. 这个隐式实现转发到具体实现。那可能是NumberProducer.get()Numberor IntegerProducer.get()Integer但不是两者兼有。这就是为什么你不能两次实现同一个接口的原因。

其他语言通过定义站点差异来允许这一点,其中Producer<Integer>是 的子类型Producer<Number>,但遗憾的是,Java 不允许。常见的解决方法是也使NumberProducer通用。

于 2013-05-07T11:17:38.220 回答
0

如果你想确保 T 是一个特定的子类型,你可以使用

interface Producer<T extends Number> 

不确定 Producer 到底是什么,所以我不得不猜测。

更新:如果我理解你是正确的,那么我会说,你需要声明一个接口,它是一个生产者。这很简单。

从这个接口我将派生一个具有相应基本类型的新接口。

IE:

 interface Producer
 {
     base functions
 };


 interface Newproducer<T extends Producer>
 {
 };

这是你的想法吗?

于 2013-05-07T11:08:39.530 回答