2012-12-18 175 views
3

我目前有以下类型的工作:具有相关泛型类型的泛型类不能专用?

// 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的值转换为Strings的类。

现在我想创建一个类,它提供类似于这样的接口:

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

的类将包装现场,并让其用户检索的字段中的值,而且还提供其他功能,包括检索标签。下面是我有:

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>并能够访问F和V.我认为这是不可能的,以上是正确的方法吗?

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

我想为中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

+0

问题是什么? –

+0

你为什么不包装自己的领域呢? – Perception

+0

我必须支持其他种类的不适合自己的领域。 – ARRG

回答

1

F可扩展Field<V>任何类型,该类型是不是necessarly一个LabelField

例如,如果您创建实现Field<Object>的类FooField,并使用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

+0

这是我实际上实现的是的,但是我们失去了字段类型的通用性(因此我们需要在调用getField()时进行投射)。你认为没有办法做得更好? – ARRG

+0

@ARRG在这种情况下,您可以通过继承Wrapper的子类 – WilQu

+0

确定。谢谢 :) – ARRG

0

您混合了泛型和继承。

您应该只与V参数化:

public class Wrapper<V> 

和下面写

Field<V> 
在所有地方

你会写

F