【问题标题】:Why is this type not a valid substitute for the type parameter?为什么这种类型不是类型参数的有效替代品?
【发布时间】:2011-10-25 08:46:47
【问题描述】:

我正在尝试使用泛型来支持委托对象(装饰器、包装器)的可配置结构。我想构建一个实现目标接口和通用委托接口的委托链。

我有这个大纲:

class Test {
    static interface Delegator<T> {}

    static class DelegatorChain<T extends Delegator<T>> {}

    static interface Foo {}

    static class FooDelegator implements Delegator<Foo>, Foo {}

    public static void main(String[] args) {
        DelegatorChain<FooDelegator> chain = new DelegatorChain<FooDelegator>();
    }
}

但是,当尝试实例化 chain 变量时,编译器会报错:

绑定不匹配:Test.FooDelegator 类型不是 Test.DelegatorChain&lt;T&gt; 类型的有界参数 <T extends Test.Delegator<T>> 的有效替代品

我承认泛型对我来说就像 magic,但我可以以某种方式承认 FooDelegator 不是 扩展 Delegator 的 Foo,它只是实现了两个接口。

鉴于我想完成什么很清楚,有什么我可以做的吗?泛型来修复它,还是我最好忘记它?

【问题讨论】:

  • 为什么你的 DelegatorChain 的泛型类型需要扩展 Delegator?您的委托人类正在提供类型信息。 Delegator 所需,FooDelegator 提供委托实现。
  • 它无法编译,因为Foo 不是Delegatornabeelalimemon.com/blog/2011/01/self-bound-generic-types
  • 是的 类型不匹配。 DelegatorChain 中的泛型类型 是“FooDelegator”,但 Delegator 中所需的泛型类型是“Foo”。您将需要我在答案中提供的额外通用类型参数,以使其按您的预期工作,我相信。或者只是离开约束。
  • 我的问题是,从设计的角度来看,DelegatorChain 是否需要知道它包含哪个 Delegator 以及 Delegator 实现的接口?该问题的答案可能会影响已提交的哪些答案更适合您的需求。
  • @ty1824,还在想……是的,它确实需要两者都知道。最后,整个结构应该能够充当 Foo。

标签: java generics


【解决方案1】:

根据您的定义,Delegator 是自身的 Delegator(例如 Comparable ),但似乎意图是 Delegator 是超类的 Delegator。幸运的是,泛型有一种表达方式:

static class DelegatorChain<T extends Delegator<? super T>> {}

这表示“Delagator 类型必须是 T 的超类”。通过此更改,您的原始代码的其余部分将编译:

static interface Delegator<T> {}
static class DelegatorChain<T extends Delegator<? super T>> {}
static interface Foo {}
static class FooDelegator implements Delegator<Foo>, Foo {}

public static void main(String[] args) {
    DelegatorChain<FooDelegator> chain = new DelegatorChain<FooDelegator>();
}

此外,无论何时您使用通用的超级绑定,您的代码看起来都非常酷 :)



注意:以下最初是问题中的“第一个选项”。
还有另一种方法可以编译你的代码,但它是次要的,因为它失去了 Delegator 类型与其委托对象之间的连接:

// Not recommended, but will allow compile:
static class FooDelegator implements Delegator<FooDelegator>, Foo {} 
// However, this also compiles :(
static class FooDelegator implements Delegator<FooDelegator>, Bar {} 

【讨论】:

  • 同意,第二种方案更简洁,只要能掌握超概念即可;-)
  • +1 我正在从另一篇文章中复制我的评论,因为第二种方法确实实现了提问者指定的内容。它指定了实现目标接口?:FooDelegators 链,以及通用Delegator 接口T:Delegator&lt;?&gt;。但是,我认为第一种方法会以不恰当的方式做到这一点。
  • 同意 - 我只是在发布后才意识到这一点。我已经编辑了答案以反映这一点。
【解决方案2】:

看起来这就是你想要做的。

static interface Delegator<T> {
    }

    static class DelegatorChain<T extends Delegator<C>, C> {
    }

    static interface Foo {
    }

    static class FooDelegator implements Delegator<Foo>, Foo {
    }

    public static void main(String[] args) {
        DelegatorChain<FooDelegator, Foo> chain = new DelegatorChain<FooDelegator, Foo>();
    }

您的初始示例无法编译,因为类型不正确。 DelegatorChain 中的泛型类型是“FooDelegator”,但 Delegator 中所需的泛型类型是“Foo”。您需要我在答案中提供的额外通用类型参数才能使其按预期工作。

您也可以完全关闭 DelegatorChain 上的约束,即 DelegatorChain。

【讨论】:

  • 不完全一样,而是正确的。它只是多余的,因为当您在另一个泛型类型声明 (T) 中使用 C 时,需要将其声明为类型。
  • +1 我相信这实现了询问者指定的内容,它指定了实现目标接口C:Foo 的委托者链,以及通用委托者接口T:@ 987654325@.
【解决方案3】:

如果是FooDelegator implements Delegator&lt;FooDelegator&gt;Foo implements Delegator&lt;Foo&gt;,则应该起作用。因为这是您对 DelegatorChain 的要求:T implements Delegator&lt;T&gt;

第三种选择,应该也可以:

DelegatorChain<T extends Delegator<F>, F> chain; ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多