假设我有一个类Foo,一个A类和一个A的子类B.Foo接受A及其子类作为泛型类型。 A和B都需要在构造函数中使用Foo实例。我希望A的Foo是A类,而B的Foo是B类或B的超类。所以实际上,我只想要这个:
Foo<X> bar = new Foo<X>;
new B(bar);
如果X是A,B或A的两个子类和B的超类,则是可能的。
到目前为止,这就是我所拥有的:
class Foo<? extends A>{
//construct
}
class A(Foo<A> bar){
//construct
}
class B(Foo<? super B> bar){
super(bar);
//construct
}
对super(...)
的调用不起作用,因为<A>
比<? super B>
更严格。在强制执行这些类型时,是否可以以某种方式使用构造函数(或通过其他方法避免代码重复)?
编辑:Foo保留泛型参数类型的元素集合,这些元素和Foo具有双向链接。因此,不应该将A链接到Foo。
答案 0 :(得分:1)
如果将A构造函数更改为:
class A(Foo<? extends A> bar){
//construct
}
它能做你想做的吗?
如果你真的想要限制A到Foo的构造函数,那么你需要提供另一个受保护的方法(也可以从派生类中使用)来设置Foo实例。 像这样:
public class A {
Foo<?> foo;
public A(Foo<A> foo) {
setFoo(foo);
}
protected A() {
}
protected void setFoo(Foo<?> foo) {
this.foo = foo;
}
}
和B
public class B extends A {
public B(Foo<? super B> foo) {
setFoo(foo);
}
}
现在可行:
new A(new Foo<A>());
new A(new Foo<B>()); // this fails compilation
new B(new Foo<B>());
为了正确输入A中的foo元素,您可能还需要使A成为参数化类。
答案 1 :(得分:0)
这样做的唯一方法就是......
class A(Foo<? extends A> bar) {
//construct
}
但看起来这不是你想要的。您不能使用其他方法,因为在创建B实例时,您还要创建A的实例(它是B实例的一部分)。因此B不能为A中的部分采用特殊字段。我不确定为什么你不允许A的foo为B类,你可以扩展它吗?
答案 2 :(得分:0)
为我编译了以下设置:
public interface MarkerInterface {
}
public class A implements MarkerInterface {
public A(Foo<A> fooA) {
}
}
public class SuperB implements MarkerInterface {
}
public class B extends SuperB {
public B(Foo<? super B> fooB) {
}
}
使用main
方法:
public static void main(String[] args) {
B b = new B(new Foo<SuperB>());
}
这是你要找的吗?
答案 3 :(得分:0)
Java泛型功能强大且设计精良;尽管如此,我们有时会发现它们缺乏。我认为没有一种好方法可以做你想做的事。
最简单的方法是将Foo<X>
的声明更改为Foo<X extends A>
。如果这是不可接受的,你可以像这样继承Foo
:
class Foo<X> { }
class FooA<X extends A> extends Foo<X> { }
class A {
public A(FooA<? extends A> foo) { }
}
class B extends A {
public B(FooA<? super B> foo) {
super(foo);
}
}
(注意:如果您在关注时遇到问题,当您看到Foo
时,请考虑ArrayList
。)
这有一个明显的缺点,你必须使用FooA
而不是Foo
,这会阻碍代码重用。