首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多次继承泛型接口,同时尊重方差

多次继承泛型接口,同时尊重方差
EN

Stack Overflow用户
提问于 2013-05-07 10:59:27
回答 3查看 923关注 0票数 1

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

代码语言:javascript
运行
复制
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>

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-07 12:29:06

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

代码语言:javascript
运行
复制
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; }
}
票数 2
EN

Stack Overflow用户

发布于 2013-05-07 11:17:38

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

代码语言:javascript
运行
复制
public static <T> T gimme(Producer<T> p) { return p.get(); }

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

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

票数 1
EN

Stack Overflow用户

发布于 2013-05-07 11:08:39

如果要确保T具有特定的子类型,则可以使用

代码语言:javascript
运行
复制
interface Producer<T extends Number> 

不知道什么是制片人雷亚尔所以我得猜猜。

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

从这个接口中,我将派生出一个新的接口,它的基类型是尊重的。

即:

代码语言:javascript
运行
复制
 interface Producer
 {
     base functions
 };


 interface Newproducer<T extends Producer>
 {
 };

你就是这么想的吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16417344

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档