Java 在考虑差异的情况下多次从通用接口继承

Java 在考虑差异的情况下多次从通用接口继承,java,generics,inheritance,Java,Generics,Inheritance,我在尝试专门化一个实现了泛型接口的类时遇到了一个问题,在这个类中,我希望继承与超级类相同的接口,但具有更具体的类型参数。下面的代码段显示了一个无法编译的合成但完整的示例。注释包含来自Java编译器的错误消息 interface Producer<T> { T get(); } class NumberProducer implements Producer<Number> { @Override public Number get() { ret

我在尝试专门化一个实现了泛型接口的类时遇到了一个问题,在这个类中,我希望继承与超级类相同的接口,但具有更具体的类型参数。下面的代码段显示了一个无法编译的合成但完整的示例。注释包含来自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; }
}
接口生成器{
T get();
}
类NumberProducer实现生产者{
@凌驾
公共编号get(){return null;}
}
//无法使用不同的参数继承Producer:和
类IntegerProducer扩展NumberProducer实现生产者{
@凌驾
公共整数get(){return null;}
}
从某种意义上说,
Producer
是生产者,因此
Producer
将是
Producer
的子类型,但在
Producer
的定义中无法声明这一点。Java不允许
IntegerProducer
同时从
NumberProducer
Producer
继承,因为
IntegerProducer
将同时从
Producer
Producer
继承


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

如果您想确保T属于您可以使用的特定子类型

interface Producer<T extends Number> 
接口生成器
我不确定reall是什么制片人,所以我不得不猜测

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

从这个接口中,我将派生一个具有respectve基类型的新接口

i、 e:

接口生成器
{
基函数
};
接口新生产者
{
};

这就是你想要的吗?

假设我们有一个简单的方法
给我

public static <T> T gimme(Producer<T> p) { return p.get(); }
public static T gimme(Producer p){return p.get();}
gimme
的上下文中,对
T
一无所知。它可以是
数字
整数
或任何其他引用类型。因此,由于擦除,编译器发出对
Producer.get()对象的接口调用,而不是对IntegerProducer.get()Integer
的特定调用。使用
T!=对象
还隐式实现了
Producer.get()对象
。此隐式实现将转发到特定实现。这可能是
NumberProducer.get()Number
IntegerProducer.get()Integer
,但不是两者都是。这就是为什么不能实现同一接口两次


其他语言通过定义站点差异来实现这一点,其中
Producer
Producer
的子类型,但遗憾的是,Java没有。常见的解决方法是将NumberProducer设置为泛型。

只需向超类添加一个参数:

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; }
}
接口生成器{
T get();
}
类NumberProducer实现生产者{
@凌驾
public T get(){return null;}
}
类IntegerProducer扩展NumberProducer{//Implicit:implements Producer
@凌驾
公共整数get(){return null;}
}

为什么要在IntegerProducer中实现接口?您可以在不实现接口的情况下重写get()方法。您能提供一个如何使用这些类的示例吗?我不确定,即使是让
NumberProducer
通用化的常见建议也能达到您的目的。如果使用
NumberProducer implements Producer
,则只能从
NumberProducer.get()
返回
null
,因为您不知道
Number
的子类型是
t
。也就是说,您不能返回
newnumber()
(我知道构造函数不存在,但请原谅我),因为
t
实际上可能是
Integer
。问题是我想使用
Producer
接口来处理与
Number
不兼容的类型,例如
String
。所以我不能在类型参数上加一个界限。更新了我的方法。不确定这是否是你的想法。对我来说,这听起来也有点像工厂,但在不知道您的意图的情况下,很难说。我确实理解,您代码片段中的调用
p.get()
将被编译为对
Producer.get()的调用对象
将由
NumberProducer
实现,但是
IntegerProducer
可以重写该方法,并让它调用
NumberProducer.get()Integer
,所以我看不出有问题。@feuermemel在具有声明站点差异的语言中是可能的
IntegerProducer.get()
将覆盖
NumberProducer.get()
。然而,在Java中,它们将是重载方法,编译器只能转发给其中一个。所以这是不允许的。这就是我现在所做的,谢谢。我引入了一个
SpecializableNumberProducer
,并使
NumberProducer
继承自它,而不添加任何实现,只传递类型参数的
Number
。这样,NumberProducer的用户就不必在每次使用时显式地将
Number
作为类型参数传递。Ben Schulz的回答中有关于泛型实现的更多细节,以及是什么阻止了我的原始代码工作。
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; }
}