繁体   English   中英

如何创建使用另一个通用 Java 接口键入的通用 Java 接口?

[英]How to create generic Java interface typed with another generic Java interface?

我们方法的目标是为我们现有的 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<UserId> 看起来也很愚蠢。 UserDao 应该是一个 Dao<User> 对象。

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

=== 选项 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, UserId> {
  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<User, UserId> 看起来很愚蠢。 我们要使用哪个ResourceId(即UserId)的信息在Resource(即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 将通过适当的调整工作得很好。 首先将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) {}
    }

由于您不需要知道在Resource类的上下文中ResourceId ( <T> ) 的泛型类型是什么,您可以使用通配符将其忽略:

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

GitHub 上的完整代码

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM