如何创建使用其他通用Java接口键入的通用Java接口?

时间:2019-05-17 23:08:45

标签: java generics interface override dao

我们方法的目标是将接口引入我们现有的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();
}


我正在努力为我们的DAO课程寻找一个可行的解决方案。这是我尝试但失败的一些方法:

===选项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 看起来也很愚蠢。 UserDao应该是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 看起来很愚蠢。我们要使用哪个ResourceId(即UserId)的信息在资源(即User)的实现中已经可用。有没有更清洁的方法?

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);
}

有什么想法可以正确解决这个问题吗?

1 个答案:

答案 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) {}
    }
}

希望这会有所帮助。