Reputation: 6934
I have an abstract factory like so:
public abstract class DAOFactory {
public abstract EntryDAO<EntryDTO> getEntryDAO();
...
}
With my DAO and DTO interfaces like so:
public interface EntryDTO extends GenericDTO {
}
public interface EntryDAO<T extends EntryDTO> extends GenericDAO<T, Serializable> {
}
And my implementation like so:
public class EntryDTOImpl implements EntryDTO {
}
public class EntryDAOImpl<T extends EntryDTO> extends GenericDaoImpl<EntryDTOImpl, ObjectId>
implements EntryDAO<T> {
}
Now, if I create a factory and override the getEntryDAO
method like so:
public class MyDAOFactory extends DAOFactory {
@Override
public EntryDAO<EntryDTO> getEntryDAO() {
try {
return new EntryDAOImpl<EntryDTOImpl>();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
I get a compile time error:
Type mismatch: cannot convert from EntryDAOImpl to EntryDAO
EDIT
I've updated my abstract factory like so:
public abstract <T extends EntryDTO> EntryDAO<T> getEntryDAO();
And made the change in my factory implementation:
@Override
public <T extends EntryDTO> EntryDAO<T> getEntryDAO() {
try {
return new EntryDAOImpl<EntryDTOImpl>();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Now I'm getting the compile time error:
Type mismatch: cannot convert from EntryDAOImpl<EntryDTOImpl> to EntryDao<T>
Upvotes: 1
Views: 404
Reputation: 79875
The reason this is happening is that you're trying to return an EntryDaoImpl<EntryDTOImpl>
, which is a subtype of EntryDao<EntryDTOImpl>
, but not of EntryDao<EntryDTO>
, which is the return type of the method.
Solution:
I believe you want to change the return type of the getEntryDao
method to
EntryDAO<? extends EntryDTO>
.
Upvotes: 1
Reputation: 729
Define the abstract method this way (notice ?
instead of T
):
public abstract EntryDAO<? extends EntryDTO> getEntryDAO(); //should work for you
I recreated the scenario the way I understood it: returning subclass1<subclass2>
as interface1<interface2>
For example, this works well:
public static List<? extends CharSequence> dostuff1() {
return new ArrayList<String>();
}
But this doesn't work:
public <B extends CharSequence> List<B> dostuff2() {
return new ArrayList<String>();
}
This gives the same compile-time error that you got: Type mismatch: cannot convert from ArrayList<String> to List<B>
Upvotes: 2
Reputation: 4571
Just change the return type from EntryDao<T>
to EntryDao<? extends T>
. That will do the trick:
@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;
}
Now as a justification, suppose EntryDao<T>
has methods that return T
like
T load(Serializable id);
and methods that accept T
like
void save(T t);
Now assume PersonDTO extends EntryDTO
, and CarDTO extends EntryDTO
.
If EntryDao<EntryDTO>
were assignable from EntryDao<EntryDTOImpl>
, it would also be assignable form EntryDao<PersonDTO>
and EntryDao<CarDTO>
.
Then you could do:
EntryDao<EntryDTO> x = new EntryDao<PersonDTO>(); // currently this is a compile time error
If that were legal, you could do:
x.save(new CarDTO()); // a run time error, because x can only save Persons, not Cars
But what is EntryDao<? extends EntryDTO>
? It is just EntryDao with all T
-accepting methods like save(T)
removed.
Upvotes: 1