【问题标题】:Java field type for a value of a generically recursive self-type?一般递归自类型的值的Java字段类型?
【发布时间】:2014-06-09 15:00:39
【问题描述】:

给定一个基类定义递归自类型的类层次结构:

abstract class A<T extends A<T>> { }

我如何声明另一个类(它在 T 中不应该是泛型的,因为这样的 T 可能在对象的生命周期内变化)具有可以包含 A 的任何子类的字段?

以下不起作用:

public class B {
    //fails to compile, because the capture of ? is not sufficiently narrow
    private A<?> a;

    public <T extends A<T>> setA(T a) {
        this.a = a;
    }
}

-- 问题结束--

我注意到许多 StackOverflow 成员倾向于用“你为什么要这样做?”来解决某些难题。以下是我使用此模式的理由——您可以注意到 Java 标准库在其 Enum 类的定义中也使用递归自类型:Enum&lt;E extends Enum&lt;E&gt;&gt;。这个问题可以类似地问为“如何定义Enum&lt;?&gt; 类型的字段。

理由示例:

abstract class A<T extends A<T>> {
    public abtract T self();
    public B<T> bify(Bifyer bifyer) {
        return bifyer.bify(self());
    }
}

带有子类:

class ASub1 extends A<ASub1> { 
    public ASub1 self() { return this; }
}       

class ASub2 extends A<ASub2> { 
    public ASub2 self() { return this; }
}       

绑定到并行类层次结构:

abstract class B<T extends A<T>> {
}

class BSub1<T extends A<T>> implements B<T> { }
class BSub2<T extends A<T>> implements B<T> { }
//and others

随着 Bifyer 接口实现管理的 B 实例的生成:

interface Bifyer {
    B<ASub1> bify(ASub1 asub1);
    B<ASub2> bify(ASub2 asub2);        
}

此接口的实现可能会为 B 返回 BSub1 或 BSub2。这本质上是访问者模式的应用程序,其中 Bifyer 是访问者,但与标准访问者不同,accept 方法返回值而不是 void。这提供了一个模块化框架,其中可以指定不同的 Bifyer 实现来为 Bify 方法提供替代行为和返回类型 - 例如为 B 的每个子类提供一个。

【问题讨论】:

  • 没有理由使用绑定的&lt;T extends A&lt;T&gt;&gt; 而不仅仅是&lt;T&gt;

标签: java generics visitor-pattern self-type


【解决方案1】:

如果您将下面的通配符? 绑定到A,它应该可以工作:

public class B {
    private A<? extends A> a;

    public <T extends A<T>> void setA(T a) {
        this.a = a;
    }
}

【讨论】:

  • 啊,谢谢!我曾尝试过 A extends A>> but 和其他排列,但我没有想到这个!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 2021-01-21
相关资源
最近更新 更多