2012-09-26 75 views
1

我有一個抽象工廠就像這樣:泛型多態混淆?

public abstract class DAOFactory { 
    public abstract EntryDAO<EntryDTO> getEntryDAO(); 
    ... 
} 

隨着我的DAO和DTO接口,像這樣:

public interface EntryDTO extends GenericDTO { 
} 

public interface EntryDAO<T extends EntryDTO> extends GenericDAO<T, Serializable> { 
} 

,我的實像這樣:現在

public class EntryDTOImpl implements EntryDTO { 
} 

public class EntryDAOImpl<T extends EntryDTO> extends GenericDaoImpl<EntryDTOImpl, ObjectId> 
implements EntryDAO<T> { 
} 

,如果我創建工廠並覆蓋getEntryDAO方法,如下所示:

public class MyDAOFactory extends DAOFactory { 
    @Override 
    public EntryDAO<EntryDTO> getEntryDAO() { 
     try { 
      return new EntryDAOImpl<EntryDTOImpl>(); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } 
    } 

我得到一個編譯時錯誤:

Type mismatch: cannot convert from EntryDAOImpl to EntryDAO

編輯

我已經更新了我的抽象工廠就像這樣:

public abstract <T extends EntryDTO> EntryDAO<T> getEntryDAO(); 

在我的工廠實現所做的更改:

@Override 
public <T extends EntryDTO> EntryDAO<T> getEntryDAO() { 
    try { 
     return new EntryDAOImpl<EntryDTOImpl>(); 
    } catch (UnknownHostException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

現在我就在編譯時錯誤:

Type mismatch: cannot convert from EntryDAOImpl<EntryDTOImpl> to EntryDao<T>

回答

2

定義抽象方法,這種方法(通知?代替T):

public abstract EntryDAO<? extends EntryDTO> getEntryDAO(); //should work for you 

我重建場景,我明白它的方式:subclass1<subclass2>interface1<interface2>

例如,這個效果很好:

public static List<? extends CharSequence> dostuff1() { 
    return new ArrayList<String>(); 
} 

但是,這並不工作:

public <B extends CharSequence> List<B> dostuff2() { 
    return new ArrayList<String>(); 
} 

這使你得到了相同的編譯時錯誤:Type mismatch: cannot convert from ArrayList<String> to List<B>

+0

請參閱編輯。 – wulfgarpro

+0

我現在已經編輯了我的答案。 – davidXYZ

+0

謝謝 - 爲什麼我不能使用一個接口作爲我的參數化類型,並且有一個實現被替換? – wulfgarpro

1

出現這種情況的原因是,你想返回一個EntryDaoImpl<EntryDTOImpl>,它是EntryDao<EntryDTOImpl>的子類型,但不是EntryDao<EntryDTO>,它是該方法的返回類型。

解決方案:

我相信你想要的getEntryDao方法的返回類型更改爲

EntryDAO<? extends EntryDTO>

+0

我已經提出了建議的更改,但仍然有問題。請參閱我的編輯。 – wulfgarpro

1

只需將返回類型從EntryDao<T>更改爲EntryDao<? extends T>即可。這將這樣的伎倆:

@Override 
public <T extends EntryDto> EntryDao<? extends T> getEntryDao() { 
    try { 
     return new EntryDAOImpl<EntryDTOImpl>(); 
    } catch (UnknownHostException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return dao; 
} 

現在,作爲一個理由,假設EntryDao<T>有返回方法T

T load(Serializable id); 

,並接受T

void save(T t); 

現在假設PersonDTO extends EntryDTO方法,和CarDTO extends EntryDTO

如果EntryDao<EntryDTO>可從EntryDao<EntryDTOImpl>轉讓,它也可以從EntryDao<PersonDTO>EntryDao<CarDTO>轉讓。

然後,你可以這樣做:

EntryDao<EntryDTO> x = new EntryDao<PersonDTO>();  // currently this is a compile time error 

如果是合法的,你可以這樣做:

x.save(new CarDTO()); // a run time error, because x can only save Persons, not Cars 

但什麼是EntryDao<? extends EntryDTO>?這只是EntryDao與所有T - 接收方法如save(T)刪除。

+0

你能解釋爲什麼我需要這樣做嗎?爲什麼我不能只用'T'? – wulfgarpro

+0

@ wulfgar.pro更新。 – Saintali

+0

我不確定我完全理解''所有'T'接受方法(如'save(T)'removed'')的含義。通過說'EntryDao '我要說的是,接受任何延伸'T'的類型,'T'是上限。如果'T'是'',那麼說'EntryDao '有什麼不同?我不認爲你可以使用'T'作爲匹配的參數化類型 - 這就是問題所在。即使在你的例子中,我仍然需要像這樣投射:'return(EntryDao )new EntryDAOImpl ();'。 – wulfgarpro