具有依赖泛型类型的泛型类,不能专门化吗?

时间:2012-12-18 11:24:23

标签: java generics

我目前正在使用以下类型:

// A Field whose values are of type V.
interface Field<V> {
    public V getValue();
}

// A Field whose values are of type V and that has a LabelProvider for those values.
interface LabelField<V> extends Field<V> {
    public LabelProvider<V> getLabelProvider();
}

这些来自图书馆,我无法改变它们。这可能不相关,但LabelProvider基本上是一个将V类型的值转换为字符串的类。

现在我想创建一个提供类似于此的接口的类:

// A Wrapper class for Fields of values V
interface IWrapper<V, F extends Field<V>> {
    public F getField();
    public V getValue();
    public String getLabel();
}

该类将包装一个Field,并让其用户从该字段中检索该值,还提供其他功能,包括检索标签。这就是我所拥有的:

public class Wrapper<V, F extends Field<V>> {

    private F field;
    private LabelProvider<V> labelProvider; // Converts from V to String

    // Since we have no guarantee that F has a LabelProvider, one is explicitely supplied.
    public Wrapper(F field, LabelProvider<V> labelProvider) {
        this.field = field;
        this.labelProvider = labelProvider;
    }

    private String getLabel() {
        return labelProvider.getLabel(field.getValue());
    }

    public F getField() {
        return field;
    }

    public V getValue() {
        return field.getValue();
    }
}
  1. 直到这一点没问题,虽然我不确定我是否需要这两种通用类型。理想情况下,我希望只有Wrapper&gt;并且能够访问F和V.我认为这是不可能的,并且上述是正确的方法吗?

  2. 现在这是真正的问题。

  3. 我想为LabelField类型设置一个更具体的构造函数,如下所示:

    public Wrapper(LabelField<V> labelField) {
        // Use the field's own label provider
        this(labelField, labelField.getLabelProvider());
    }
    

    在这种情况下,可以从字段中提取labelprovider。但编译器不喜欢这样,我得到以下错误:

    The constructor Wrapper<V,F>(LabelField<V>, LabelProvider<V>) is undefined
    

    即使这个使用相同类型的方法编译:

    public static <X> void test(LabelField<X> lf) {
        LabelProvider<X> lp = lf.getLabelProvider();
        new Wrapper<X, LabelField<X>>(lf, lp);
    }
    

    为什么第二个构造函数不能编译?

    这是一个SSCE:http://pastebin.com/UqLJhJA7

2 个答案:

答案 0 :(得分:1)

F可以是任何扩展Field<V>的类型,而且该类型不一定是LabelField

例如,如果您创建实现FooField的类Field<Object>并使用Wrapper<Object, FooField>,则LabelField构造函数将不匹配。

您可以通过这种方式简化您的包装(这也可以回答您的第一点):

public class Wrapper<V> {

    private Field<V> field;

    private LabelProvider<V> labelProvider; // Converts from V to String

    // Since we have no guarantee that F has a LabelProvider, one is explicitely
    // supplied.
    public Wrapper(Field<V> field, LabelProvider<V> labelProvider) {
        this.field = field;
        this.labelProvider = labelProvider;
    }

    public Wrapper(LabelField<V> labelField) {
        // Use the field's own label provider
        this(labelField, labelField.getLabelProvider());
    }

    private String getLabel() {
        return this.labelProvider.getLabel(this.field.getValue());
    }

    public Field<V> getField() {
        return this.field;
    }

    public V getValue() {
        return this.field.getValue();
    }
}

这使用“常规”多态而不是field的泛型。

答案 1 :(得分:0)

你混合了泛型和继承。

您应该仅使用V进行参数化:

public class Wrapper<V>

并写在下面

Field<V>

在你要写的所有地方

F