Java隐式来自超类的通用参数

时间:2014-08-21 00:25:33

标签: java

编辑:我让这个例子简单得多了

我想创建一个带有泛型参数的类,该类扩展了带有泛型参数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是这里唯一可用的选项,应该隐式知道

2 个答案:

答案 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
    }
}