2012-12-18 174 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