Consider the following code:
public abstract class MyObject {
}
public interface Dao<T extends MyObject> {
}
public abstract class JsonDao<T extends MyObject> implements Dao<T> {
}
public abstract class SqliteDao<T extends MyObject> implements Dao<T> {
}
public interface DaoFactory<*????*> {
public *????* getDao(Class<? extends MyObject> objectClass);
}
Now what I'd like is for getDao to be able to instanciate both JsonDao and SqliteDao, but parametrized with a class extending MyObject, basically something like this:
public interface DaoFactory<T<? extends MyObject> extends Dao<? extends MyObject>> {
public <U extends MyObject> T<U> getDao(Class<U> objectClass);
}
Is something similar even possible or does type erasure prevent it?
Does this fit your needs?
public interface DaoFactory<O extends MyObject, D extends Dao<O>> extends Dao<O> {
public D getDao(Class<O> objectClass);
//or for any subclass
public <RO extends O, RD extends D<RO>> RD getSubDao(Class<RO> objectSubclass);
//or maybe this
public <RO extends O> Dao<RO> getSimpleSubDao(Class<RO> objectSubclass);
}
You could declare DaoFactory
as follows:
public interface DaoFactory<D extends Dao<? extends MyObject>> {
<T extends MyObject> D getDao(Class<T> type);
}
Then, JsonDaoFactory
could be implemented as follows:
public class JsonDaoFactory implements DaoFactory<JsonDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, JsonDao<? extends MyObject>> daos =
new HashMap<>();
public JsonDaoFactory() {
daos.put(Contact.class, new JsonContactDao());
daos.put(Customer.class, new JsonCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> JsonDao<T> getDao(Class<T> type) {
return (JsonDao<T>) daos.get(type);
}
}
I've used a Map
to make every descendant of MyObject
match its corresponding JsonDao
(here I've used Contact
and Customer
, and JsonContactDao
and JsonCustomerDao
, respectively). I've suppressed an unchecked cast warning because I'm explicitly filling the map in the constructor, so I'm sure there won't be a ClassCastException
.
For completeness, here's the code for SqliteDaoFactory
:
public class SqliteDaoFactory implements DaoFactory<SqliteDao<? extends MyObject>> {
private final Map<Class<? extends MyObject>, SqliteDao<? extends MyObject>> daos =
new HashMap<>();
public SqliteDaoFactory() {
daos.put(Contact.class, new SqliteContactDao());
daos.put(Customer.class, new SqliteCustomerDao());
}
@Override
@SuppressWarnings("unchecked")
public <T extends MyObject> SqliteDao<T> getDao(Class<T> type) {
return (SqliteDao<T>) daos.get(type);
}
}
The code for both factories is almost duplicated, but I couldn't find a way to solve this.
Here's how to use these factories:
JsonDaoFactory jsonDaoFactory = new JsonDaoFactory();
JsonDao<Contact> contactJsonDao = jsonDaoFactory.getDao(Contact.class);
JsonDao<Customer> customerJsonDao = jsonDaoFactory.getDao(Customer.class);
SqliteDaoFactory sqliteDaoFactory = new SqliteDaoFactory();
SqliteDao<Contact> contactSqliteDao = sqliteDaoFactory.getDao(Contact.class);
SqliteDao<Customer> customerSqliteDao = sqliteDaoFactory.getDao(Customer.class);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.