簡體   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