我们方法的目标是将接口引入我们现有的DAO和模型类。模型类由各种类型的资源ID标识,资源ID不仅是随机数,而且还具有语义和行为。因此,我们必须通过对象而不是原始类型来表示资源ID。
当前资源ID的方法:
interface ResourceId<T> {
T get();
}
class UserId implements ResourceId<String> {
public String get();
}
我们的资源/模型的当前方法:
interface Resource<I extends ResourceId> {
I id();
}
class User implements Resource<UserId> {
public UserId id();
}
===选项1 ===
失败:
error: > expected
Java中似乎禁止使用多个级别的泛型类型
interface Dao<R extends Resource<I extends ResourceId>> {
R findById(I id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(UserId id);
public void save(User u);
}
===选项2 ===
失败:
UserDao is not abstract and does not override abstract method <R>save(R) in Dao
Dao
interface Dao<I extends ResourceId> {
<R extends Resource<I>> R findById(I id);
<R extends Resource<I>> void save(R u);
}
class UserDao implements Dao<UserId> {
public User findById(UserId id);
public void save(User u);
}
===选项3 ===
失败:
UserDao is not abstract and does not override abstract method <I>findById(I) in Dao
即使有效,我也不受R实际实现的ResourceId约束。
interface Dao<R extends Resource> {
<I extends ResourceId> R findById(I id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(UserId id);
public void save(User u);
}
===选项4 ===
编译。
但是,UserDao中的#findById必须采用ResourceId类型的通用参数,而不是UserId。另外,在#findById的实现内部,我们必须将#get()的结果强制转换为String。
通常,问题在于ResourceId的类型不受R实际实现的ResourceId约束。
interface Dao<R extends Resource> {
R findById(ResourceId id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(ResourceId id);
public void save(User u);
}
===选项5 ===
编译。
但是Dao
interface Dao<R extends Resource, I extends ResourceId> {
R findById(I id);
void save(R u);
}
class UserDao implements Dao<User, UserId> {
public User findById(UserId id);
public void save(User u);
}
有什么想法可以正确解决这个问题吗?
答案 0 :(得分:2)
您的选项一可以通过适当地调整来找到。首先将ResourceId
泛型类型规范添加到您的Dao
声明中:
static interface Dao<I extends ResourceId<?>, R extends Resource<I>> {
R findById(I id);
void save(R u);
}
,然后对Dao
子类进行相同操作:
static class UserDao implements Dao<UserId, User> {
public User findById(UserId id) { return null; }
public void save(User u) {}
}
由于您无需知道ResourceId
类的上下文中<T>
(Resource
)的通用类型是什么,因此可以使用通配符:
static interface Resource<I extends ResourceId<?>> {
I id();
}
最后,完整代码将编译为:
public class NestedGenerics {
static interface ResourceId<T> {
T get();
}
static class UserId implements ResourceId<String> {
public String get() { return null; }
}
static interface Resource<I extends ResourceId<?>> {
I id();
}
static class User implements Resource<UserId> {
public UserId id() { return null; }
}
static interface Dao<I extends ResourceId<?>, R extends Resource<I>> {
R findById(I id);
void save(R u);
}
static class UserDao implements Dao<UserId, User> {
public User findById(UserId id) { return null; }
public void save(User u) {}
}
}
希望这会有所帮助。