当我试图专门化一个实现泛型接口的类时,我遇到了一个问题,在这个类中,我想继承与超类相同的接口,但是使用一个更具体的类型参数。下面的片段显示了一个无法编译的合成但完整的示例。注释包含来自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
同时从NumberProducer
和Producer<Integer>
继承,而IntegerProducer
则同时继承Producer<Integer>
和Producer<Number>
。
是否有一种标准的方法来解决这一限制,例如,一种不需要这种继承就可以解决相同问题的模式?
发布于 2013-05-07 12:29:06
只需向超类添加一个参数:
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-07 11:17:38
假设我们有一个简单的方法gimme
。
public static <T> T gimme(Producer<T> p) { return p.get(); }
在gimme
的上下文中,对T
一无所知。它可以是Number
、Integer
或任何其他引用类型。因此,由于擦除,编译器发出对Producer.get()Object
的接口调用,而不是对IntegerProducer.get()Integer
的特定调用。使用Producer<T>
实现T != Object
的所有类型也都隐式实现了Producer.get()Object
。此隐式实现将转发到特定的实现。这可能是NumberProducer.get()Number
或IntegerProducer.get()Integer
,但两者都不是。这就是为什么不能实现同一接口两次的原因。
其他语言通过定义站点方差(其中Producer<Integer>
是Producer<Number>
的一个子类型)允许这样做,但是遗憾的是,Java不允许这样做。常见的解决方法是使NumberProducer
也是通用的。
发布于 2013-05-07 11:08:39
如果要确保T具有特定的子类型,则可以使用
interface Producer<T extends Number>
不知道什么是制片人雷亚尔所以我得猜猜。
更新:如果我理解你的正确,那么我会说,你需要声明一个界面,它是一个生产者。这很简单。
从这个接口中,我将派生出一个新的接口,它的基类型是尊重的。
即:
interface Producer
{
base functions
};
interface Newproducer<T extends Producer>
{
};
你就是这么想的吗?
https://stackoverflow.com/questions/16417344
复制相似问题