2012-06-07 96 views
3

我無法找到一種方式,似乎並沒有錯的方式來做到這一點,下面給出如何將實現器在一個接口上轉換爲另一個接口?

public interface IType {} 
public interface IMode {} 

public interface Factory<T extends IType> { 
    IMode get(T o); 

    Class<T> getIType(); 
} 

我上面的接口和類的大名單的同時實現ITypeIMode與相應的工廠。

我需要能夠從一個轉換到另一個,例如,

public class A implements IType {} 
public class One implements IMode {} 

public class AToOne implements Factory<A> { 
    public IMode get(A o){ 
     return new One(); 
    } 

    public Class<A> getIType(){ 
     return A.class; 
    } 
} 

鑑於存在這些類的1對1映射,即對於每一個具體的IType有一個並且只有一個具體IMode與相應的工廠,我該如何將IType的列表轉換爲IMode的列表?

即,

private List<Factory<? extends IType>> factoryList; 

public List<IMode> getConversions(List<? extends IType> types){ 
    ??? 
} 

我第一次嘗試並不那麼好走,

//Fill this using the getIType() method from each factory 
Map<Class<IType>, Factory<? extends IType>> factoryList = new HashMap<Class<IType>, Factory<? extends IType>>(); 

public List<IMode> getConversions(List<IType> types){ 
    List<IMode> modes = new ArrayList<IMode>(); 

    for(IType type : types){ 
     //Derp 
     Factory<? extends IType> factory = factoryList.get(type.getClass()); 
     //Error 
     factory.get(factory.getIType().cast(type)); 
    } 
} 

錯誤:

The method get(capture#12-of ? extends IType) in the type 
Factory<capture#12-of ? extends IType> 
is not applicable for the arguments (capture#14-of ? extends IType) 
+0

到底什麼是你的問題?您的方法背後的一般想法對我來說似乎很好。 – Voo

+0

@Voo在上面的概述中,'type.getClass()'返回的是與我放入地圖中不匹配的具體類,然後我不知道如何將輸入投射到工廠,確實得到了,因爲不能保證它們是相同的。我寫的東西沒有編譯。 – Andrew

+0

啊所以你的問題不是一般的設計方法,而是泛型部分。這應該很容易修復,讓我試試:) – Voo

回答

2

就像我在我的評論中提到的,你只需要使用通用的輔助方法來訪問地圖,什麼是在傳遞來執行從Factory<? extends IType>Factory<T>,其中T的類型相匹配的未經檢查的轉換:

Map<Class<? extends IType>, Factory<? extends IType>> factoryList = 
     new HashMap<Class<? extends IType>, Factory<? extends IType>>(); 

private <T extends IType> IMode convert(T iType) { 
    //unchecked cast - implementation must guarantee map holds correct data 
    Factory<T> factory = (Factory<T>)factoryList.get(iType.getClass()); 
    //then convert 
    return factory.get(iType); 
} 

您還可以從循環這個輔助方法:

public List<IMode> getConversions(List<IType> types) { 
    List<IMode> modes = new ArrayList<IMode>(types.size()); 
    for (IType type : types) { 
     IMode iMode = convert(type); 
     modes.add(iMode); 
    } 
    return modes; 
} 
+0

謝謝,這就是我最終做的事情,我還需要遍歷IType的所有聲明類,因爲'getClass'返回的是具體類而不是接口。男人覺得很髒。 – Andrew

+0

雖然你想要的不是具體的類嗎?這就是工廠地圖中的關鍵所在。 –

+0

糟糕是啊,我的實際代碼更復雜,我有擴展我具體的'IMode'類的子類。只是細節,感謝所有的幫助。 – Andrew

1

簡單的解決辦法是:

interface IFoo { 
} 

interface IBar { 
} 

private static class Foo implements IFoo { 
} 

private static class Bar implements IBar { 
} 

interface IFoo2IBarConverter<B extends IBar, F extends IFoo> { 
    B convert(F foo); 
} 

private static class Foo2BarConverter implements IFoo2IBarConverter<Bar, Foo> { 
    public Bar convert(Foo foo) { 
     return new Bar(); 
    } 
} 

private static class IFoo2IBarFactory { 
    private static HashMap<Class<? extends IFoo>, IFoo2IBarConverter<? extends IBar, ? extends IFoo>> converters = new HashMap<>(); 

    static { 
     converters.put(Foo.class, new Foo2BarConverter()); 
    } 

    public static<F extends IFoo, B extends IBar> B convert(F foo) { 
     // ugly unchecked cast here 
     IFoo2IBarConverter<B, F> converter = (IFoo2IBarConverter<B, F>) converters.get(foo.getClass()); 
     return converter.convert(foo); 
    } 
} 


public static void main(String[] args) { 
    Foo foo = new Foo(); 
    IBar bar = IFoo2IBarFactory.convert(foo); 
} 

您只需要一個HashMap,它將某個子類型爲IFoo的特定類映射到某個轉換器接口。轉換器將IFoo實例轉換爲IBar ..實際上轉換爲我們想要的特定類。可悲的是,我們在IFoo2IBarFactory.convert()中得到了一個醜陋的演員陣容,我不認爲有什麼辦法可以避開那個。至少它只是在一個本地化的位置,並與正確的評論和SuppressWarning你可以忍受它,我會認爲

+0

我不確定你需要IFoo2IBarConverter接口。只要有與IBar對應的類並使用它來投射。例如'Class clazz = converters.get(foo);返回clazz.cast(foo);' – user949300

+0

@ user949300不知道我關注。是的,您可以通過使用原始對象並在'convert'內使用大型開關來獲得界面,但這非常*難看,並且不會贏得我們任何東西。編輯完成後:您可以調用類對象的靜態方法嗎?不知道的是,我仍然會用分裂的解決方案 - 看起來更清潔。 – Voo

+0

'B extends IBar'不應該被宣佈爲'convert',因爲主叫方決定什麼是沒有限制的,這很容易導致堆污染。該方法應該返回'IBar'。 –

相關問題