2013-10-16 78 views
0

我想創建一個通用包裝的工廠方法,我有問題,我需要傳遞所需的返回類型(wrapTyped() - 方法),或者我必須明確將輸入參數轉換爲所需的返回類型(wrapAuto() - 方法,第一次使用)。但我是懶惰並不想寫額外的演員:)鑄造通用返回類型到接口類型

是否有任何方式來表達wrapAuto()的聲明,以便案例「wantThis」(在最底部)的作品?

public class GenericFactory { 

static class Wrapper<T> { 
    T wrappdObject; 
    boolean flag; 
    String name; 

    public Wrapper(T wrappedObject, boolean flag, String name) { 
     this.wrappdObject = wrappedObject; 
     this.flag = flag; 
     this.name = name; 
    } 

    public T getObject() { 
     return wrappdObject; 
    } 

    // some more irrelevant methods 
} 

static interface InterfaceType { 
} 

static class ImplementationA implements InterfaceType { 
} 

static <U> Wrapper<U> wrapTyped(Class<U> type, U wrappedObject, boolean flag, String name) { 
    return new Wrapper<U>(wrappedObject, flag, name); 
} 

static <U> Wrapper<U> wrapAuto(U wrappedObject, boolean flag, String name) { 
    return new Wrapper<U>(wrappedObject, flag, "NoName"); 
} 

// compiles, but is cumbersome 
public Wrapper<InterfaceType> cumbersome = wrapTyped(InterfaceType.class, new ImplementationA(), true, "A"); 

// compiles, but is also cumbersome 
public Wrapper<InterfaceType> alsoUgly = wrapAuto((InterfaceType) new ImplementationA(), true, "B"); 

// Want this, but "Type mismatch error" 
public Wrapper<InterfaceType> wantThis = wrapAuto(new ImplementationA(), false, "C"); 

} 

爲了簡單起見,我簡化了它,我只聲明瞭一組接口和具體實現。我練習類包裝可能會用於許多完全不同的,不相關的類型。

回答

3

在你的方法wrapAuto,添加其他類型的參數,用U爲上限,並把它作爲正式參數類型:

static <U, T extends U> Wrapper<U> wrapAuto(T wrappedObject, boolean flag, String name) { 
    return new Wrapper<U>(wrappedObject, flag, "NoName"); 
} 

,然後這會工作:

Wrapper<InterfaceType> wantThis = wrapAuto(new ImplementationA(), false, "C"); 

隨着這個調用T被推斷爲ImplementationA,並且U被推斷爲InterfaceType。並且邊界​​完全匹配這些類型。


參考文獻:

+0

哇,美麗而簡單。甚至Wrapper n = wrapAuto(7,...);像現在的魅力一樣工作。 – Durandal

+0

開始的方法簽名沒有任何問題。這是一個推論問題。我不認爲爲該方法增加額外的不必要的類型參數是處理它的好方法。 – newacct

0

你寫的方法沒有問題。但推論並不完美。你總是可以明確指定類型參數:

public Wrapper<InterfaceType> wantThis = GenericFactory.<InterfaceType>wrapAuto(new ImplementationA(), false, "C");