编辑:我让这个例子简单得多了
我想创建一个带有泛型参数的类,该类扩展了带有泛型参数X的类型,我想引用那个类型X而不明确声明它。
我不确定这是否也回答Why can't I use a type argument in a type parameter with multiple bounds?
class Fruit<T> {}
// I don't want to have to redefine T e.g. <F extends Fruit<T>,T>
// because T should be implicit for Fruit (see Example of instance below)
// the below will not compile, but is roughly what I'd like
class Box<F extends Fruit<T>> {
T get( F fruit ) { return null; }
}
实例示例
class Apple extends Fruit<String>
// this is what I would like, but this won't compile with above definiton
class AppleBox extends Box<Apple> {
// String get( Apple apple ) should be implicit
}
我不想宣布
class AppleBox extends Box<Apple,String>
因为String是这里唯一可用的选项,应该隐式知道
答案 0 :(得分:0)
Fruit类中泛型类型的范围属于Fruit本身。该泛型类型变量不能在类外部访问。
因此,您必须定义T
来取代泛型类型,并且由于您在其他地方使用变量T
,因此您也不能将其删除。
所以重申水果中的T
类型仅在类型水果中可见,因此要在Box中使用它,您需要在某处再次定义该类型:
public class Outer {
class Fruit<T> {
T body;
}
abstract class Box<F extends Fruit<T>, T> {
abstract T get( F fruit );
}
}
如果你希望T
隐含给Fruit,那么就不要在Fruit类中定义泛型参数T
,而是在外层类中定义。
public class Outer<T> {
class Fruit {
T body;
}
abstract class Box<F extends Fruit> {
abstract T get( F fruit );
}
}
这个范围问题的类比是以下代码:
for (int i = 0; i < 10; i++) {
// stuff
}
for (int i = 0; i < 20; i++) { // i from previous loop is not visible here
// stuff
}
System.out.println(i); // variable not defined: i
答案 1 :(得分:0)
编辑解决方案:
interface Fruit<T> {
T get();
}
class Box<F extends Fruit<?>> {
<R> R get(F fruit) {
@SuppressWarnings("unchecked")
R ret = (R) fruit.get();
return ret;
}
}
class Apple implements Fruit<String> {
@Override
public String get() {
return "Apple";
}
}
class Something implements Fruit<String> {
@Override
public String get() {
return "Something";
}
}
//this is what I would like, but this won't compile with above definiton
class AppleBox extends Box<Apple> {
// ...
}
class Main {
public static void main(String[] argv) {
Apple apple = new Apple();
Something something = new Something();
AppleBox ab = new AppleBox();
System.out.println( ab.get(apple) );
// this will fail
System.out.println( ab.get(something) );)
}
}
如果你想要更多关于Box.get()返回类型的类型安全性,只需使用静态方法,因为上面的Box.get()返回Object而不是T.
interface Fruit<T> {
T get();
}
class Box<F extends Fruit<?>> {
<R> R get(F fruit) {
@SuppressWarnings("unchecked")
R ret = (R) fruit.get();
return ret;
}
public static <P, Q extends Fruit<P>> P get(Box<Q> box, Q fruit) {
return box.get(fruit);
}
}
class Apple implements Fruit<String> {
@Override
public String get() {
return "Apple";
}
}
class Something implements Fruit<String> {
@Override
public String get() {
return "Something";
}
}
//this is what I would like, but this won't compile with above definiton
class AppleBox extends Box<Apple> {
// ...
}
class Main {
public static void main(String[] argv) {
Apple apple = new Apple();
Something something = new Something();
AppleBox ab = new AppleBox();
System.out.println( AppleBox.get(ab, apple) );
System.out.println( AppleBox.get(ab, something) ); // this will fail
Apple p = AppleBox.get(ab, apple); // fail: return type mismatch
}
}