2014-03-07 157 views
0

我已經編寫了一個使用Java編寫的converter structure,我想創建一個工廠。在Java中使用泛型子類型對象創建泛型工廠

我的基本想法是,我傳入一個有效類型的類並接收一個有效的子類型轉換器,但失敗的泛型和繼承部分。

這是我的接口:

interface ItemRequestConverterFactory { 

    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> clazz); 

} 

和實現:

public class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory { 

    @Override 
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> clazz) { 
    if (clazz.equals(CreatePartRequestConverter.class)) 
    return new CreatePartRequestConverter(); 

    return null; 
    } 

} 

不幸的是,Eclipse的說: 「類型不匹配:不能從CreatePartRequestConverter轉換爲ItemRequestConverter」。

我的通用簽名中的問題在哪裏?

回答

3

您似乎在類型參數和它們應該實際表示的類型之間不匹配:您正在將Class<IR>傳遞給newInstance方法。這是代表ItemRequest的課程。但是,您正在將此類實例與可能實現ItemRequestConverter接口的類進行比較。

雖然這編譯時加適當的類型參數的CreatePartRequestConverter類,這可能不是你想要達到的目標:

interface ItemRequestConverter<IR extends ItemRequest>{} 
interface ItemRequest{} 
interface ItemRequestConverterFactory 
{ 
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> itemRequestClass); 
} 
class CreatePartRequestConverter<IR extends ItemRequest> implements ItemRequestConverter<IR> 
{ 
} 

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{ 

    @Override 
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> itemRequestClass) 
    { 
     // Does not make sense: Comparing ItemRequest class with something 
     // that is probably an implementation of ItemRequestConverter 
     if (itemRequestClass.equals(CreatePartRequestConverter.class)) 
     { 
      return new CreatePartRequestConverter<IR>(); 
     } 
     return null; 
    } 
} 

取決於你真正想要達到的目標,你可以通過ItemRequestConverter類工廠方法(和相應的參數化方法):

interface ItemRequestConverter<IR extends ItemRequest>{} 
interface ItemRequest{} 
interface ItemRequestConverterFactory 
{ 
    public <IRC extends ItemRequestConverter<?>> ItemRequestConverter<?> newInstance(Class<IRC> itemRequestConverterClass); 
} 
class CreatePartRequestConverter implements ItemRequestConverter<ItemRequest> 
{ 
} 

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{ 
    @Override 
    public <IRC extends ItemRequestConverter<?>> ItemRequestConverter<?> newInstance(
     Class<IRC> itemRequestConverterClass) 
    { 
     if (itemRequestConverterClass.equals(CreatePartRequestConverter.class)) 
     { 
      return new CreatePartRequestConverter(); 
     } 
     return null; 
    } 
} 

如果您還需要了解的ItemRequest類的信息,該方法簽名會開始變得有點討厭,並且必須更詳細地分析其中如何提供或使用此類型的信息


編輯的評論:

我認爲這是不可能的(編譯時)類型檢查的方式。這裏的問題是,在您創建並返回新的ItemRequestConverter時,您無法確定它是否爲ItemRequestConverter,其類型參數爲IR。或者相反:在編譯時您無法檢測到CreatePartRequestConverter(即CreatePartRequest)的類型參數與IR相同。

基於到目前爲止討論的代碼片段,我覺得應該可以簡單地投在這種情況下。確保投是有效的,然後留給誰實現了一個負責「運行時類型檢查」:

if (itemRequestClass.equals(CreatePartRequest.class)) 
{ 
    CreatePartRequestConverter result = new CreatePartRequestConverter(); 
    return (ItemRequestConverter<IR>) result; 
} 

,因爲沒有什麼阻止你寫

//       !!! 
if (itemRequestClass.equals(SomeCompletelyDifferentRequest.class)) 
{ 
    CreatePartRequestConverter result = new CreatePartRequestConverter(); 
    return (ItemRequestConverter<IR>) result; 
} 

所以有效做到這一點:

interface ItemRequestConverter<IR extends ItemRequest>{} 
interface ItemRequest{} 
interface ItemRequestConverterFactory 
{ 
    public <IR extends ItemRequest> ItemRequestConverter<IR> 
     newInstance(Class<IR> itemRequestClass); 
} 

class CreatePartRequest implements ItemRequest {} 
class CreatePartRequestConverter 
    implements ItemRequestConverter<CreatePartRequest> {} 

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{ 
    @Override 
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(
      Class<IR> itemRequestClass) 
    { 
     if (itemRequestClass.equals(CreatePartRequest.class)) 
     { 
      CreatePartRequestConverter result = new CreatePartRequestConverter(); 
      return (ItemRequestConverter<IR>) result; 
     } 
     return null; 
    } 
} 

public class GenericFactoryTest 
{ 
    public static void main(String[] args) 
    { 
     ItemRequestConverterFactory factory = null; 
     ItemRequestConverter<CreatePartRequest> converter = 
      factory.newInstance(CreatePartRequest.class);   
    } 
} 
+0

這不完全是我想要實現的。我的目標是:'ItemRequestConverter 轉換器= factory.newInstance(CreatePartRequest.class)'。 –

+0

@ Michael-O:添加了一個編輯 - 我認爲這是不可能的類型安全的方式.... – Marco13

+0

我已經指出了這樣的事情。演員是必要的。主要原因可能是類型擦除。 –