2013-11-20 73 views
4

對不起,在這個問題上任何不好的英語語言。通用工廠的泛型和類型推斷

我想要創建一種工廠,它只能創建由具體工廠實例類實現的列表中定義的類的實例。首先,我定義這個接口:

public interface ValuesSystem { 

    public interface AllowedValue<T extends Class<? extends SystemValue>>{}; 

    AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id); 

    Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues(); 

    <T extends SystemValue> T create(AllowedValue<Class<T>> allowedClass, ValueData data) throws InvalidValueException; 
} 

接口一個allowedValue只是一個「標誌包裝」使用泛型來定義「允許」類實例的接口是由我廠創建。

getAllowedValue是一個方法,用於從我的允許類「list」中使用來自實現此接口的具體類的內部枚舉(具體類的示例即將發佈)來獲取包裝的允許的類實例。

create方法的目的是最終創建允許的類實例的實例,在allowedClass參數中給出。

這裏是一個具體的類實現此接口的一個例子:

public class BasicValueSystem implements ValuesSystem { 

    public BasicValueSystem() { 
     super(); 
     allowedValues = (Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>) getAllowedValues(); 
    } 

    public static enum VALUES_ID { 
     MODIFIER 
    } 

    private static Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowedValues; 

    private class BasicAllowedValue<T extends Class<? extends SystemValue>> 
      implements AllowedValue<Class<? extends SystemValue>> { 

    } 

    @Override 
    public <T extends SystemValue> T create(
      AllowedValue<Class<T>> allowedClass, ValueData data) 
       throws InvalidValueException { 
     if (!(allowedClass instanceof BasicAllowedValue)) { 
      throw new InvalidValueException(); 
     } 
     return null; 
    } 

    @Override 
    public AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id) { 
     return allowedValues.get(id); 
    } 

    @Override 
    public Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues() { 
     Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowed = new EnumMap<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>(VALUES_ID.class); 
     allowed.put(VALUES_ID.MODIFIER, new BasicAllowedValue<Class<ModifierValue>>()); 
     return allowed; 
    } 
} 

眼下create方法返回null,但問題是在其他地方,這不是我的問題

的點

BasicValueSystem bvs = new BasicValueSystem(); 
AllowedValue<Class<? extends SystemValue>> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 

編譯器告訴我:當我試圖創建下面的代碼我的「允許」值實例的一個實例出現問題:

The method create(ValuesSystem.AllowedValue<Class<T>>, ValueData) in the type BasicValueSystem is not applicable for the arguments (ValuesSystem.AllowedValue<Class<? extends SystemValue>>, ModifierValueData) 

我想我錯過了關於一般泛型所做的類型推斷。

任何人都可以解釋我的創建方法簽名不適用在這種情況下,以及如何解決它?

在此先感謝您抽出時間。

+0

我真的不明白的'VALUES_ID'枚舉的作用在這裏:做這樣當它也會起作用。目前,您的'allowedValues'地圖只包含一個條目。你能解釋一下嗎?順便說一句,爲什麼你不讓自己的類通用自己? –

+0

在該示例中是,它包含一個唯一的枚舉值。這只是爲了簡化。枚舉和EnumMap旨在包含幾個值(用於enum)和AllowedValue對象(用於EnumMap) – Mirouf

+0

那麼,您是否遍歷enum'values()'以將條目添加到映射?你可以只發布你的getAllowedValues實際上是怎麼樣的嗎? –

回答

3

請注意,public interface AllowedValue<T extends Class<? extends SystemValue>>沒有多大意義。 T唯一有效的類型將是Class<? extends SystemValue>,因爲類Class是最終的並且不能有子類。所以你可以用interface AllowedValue<Class<? extends SystemValue>>來代替它,但語義沒有任何變化,但你真正意義的是(imho)是interface AllowedValue<T extends SystemValue>。不要在類型簽名中混入Class。界面仍然可能有方法參照Class<T>然後。

public interface ValuesSystem { 

    public interface AllowedValue<T extends SystemValue>{}; 

    AllowedValue<? extends SystemValue> getAllowedValue(Enum<?> id); 

    public <T extends SystemValue> T create 
        (AllowedValue<T> allowedClass, ValueData data); 
} 

適應實施相應,BasicAllowedValue成爲

private class BasicAllowedValue<T extends SystemValue> implements AllowedValue<T> 

然後用使用代碼的問題就消失了。

BasicValueSystem bvs = new BasicValueSystem(); 
AllowedValue<? extends SystemValue> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 

將編譯。


注意,如果AllowedValue應仍然沒有方法的標誌接口而已,這是不必要的,Class<T>已經實現了這一角色。

public interface ValuesSystem { 
    Class<? extends SystemValue> getAllowedValue(Enum<?> id); 
    public <T extends SystemValue> T create(Class<T> allowedClass, ValueData data); 
} 

BasicValueSystem bvs = new BasicValueSystem(); 
Class<? extends SystemValue> allowed = bvs 
    .getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER); 
bvs.create(allowed, new ModifierValueData()); 
+0

感謝它的工作,我現在的工作是瞭解我的錯誤。謝謝你的時間 – Mirouf