簡體   English   中英

正確使用Comparable與泛型

[英]Proper use of Comparable with generics

我在使接口以我想要使用泛型的方式工作時遇到了麻煩。

我有一個CRUD風格的界面來處理各種對象的數據訪問。 Comparable<?>用於通過標識符獲取對象,因為對象可能具有不同類型的標識符:

public interface DataProvider<T> {
  T create(T object);
  T get(Comparable<?> id);
  void update(T object);
  void delete(T object);
}

現在想象一個需要訪問的此類(人為)對象Book

public class Book implements Comparable<Book> {

  private ISBN isbn;

  public int compareTo(Book other) {
    return getIsbn().compareTo(other.getIsbn());
  } 

  // ...
}

我想做的是這樣的:

public class BookDataProvider implements DataProvider<Book> {
  public Book create(Book book) { ... }
  public Book get(ISBN isbn) { ... }
  public void update(Book book) { ... }
  public void delete(Book book) { ... }
}

修改DataProvider和/或Book以允許get(ISBN)編譯的最簡單方法是什么?

我已經提出了一些部分解決方案,但是我不確定哪一個是最佳的:

  • 鍵入DataProvider作為DataProvider<T, I extends Comparable<I>> ,但是這增加了額外的類型參數。
  • 在每個相關文章中引入一個Identifiable接口,使Book實現它,並在DataProvider<T extends Identifiable<?>>鍵入DataProvider ,但是然后我沒有實現get(ISBN)的簽名。

理想情況下,我想限制DataProvider僅具有一個類型參數。 我也對其他方法持開放態度。 謝謝。

使用具有可比性的專用getter方法的參數是不恰當的。 理想情況下,您的get方法不應適用於任何Comparable。 僅適用於ISBN等特定類型。 因此,我建議不要為可比較的泛型而苦苦掙扎,而應使用此類標識符的通用接口。

讓我們從部分選項中采用第二種方法並創建一個解決方案。 下面是我建議的代碼。

public class TestGenerics {
    public static void main(String[] args) {

    }
}

interface Identifiable<T extends Identifier> {
    T getIdentifier();
}

interface Identifier {

}

class Book implements Comparable<Book>, Identifiable<ISBN> {

    private ISBN isbn;

    public int compareTo(Book other) {
        return getIdentifier().compareTo(other.getIdentifier());
    }

    public ISBN getIdentifier() {

        return null;
    }

}

class ISBN implements Comparable<ISBN>, Identifier {

    public int compareTo(ISBN o) {
        return 0;
    }

}

interface DataProvider<T extends Identifiable<? extends Identifier>> {
    T create(T object);

    T get(Identifier id);

    void update(T object);

    void delete(T object);
}

class BookDataProvider implements DataProvider<Book> {

    public Book create(Book book) {
        return null;
    }

    public void update(Book book) {
    }

    public void delete(Book book) {
    }

    public Book get(Identifier id) {
        // TODO Auto-generated method stub
        return null;
    }

}

現在,這種方法是真正通用的,因為在頂層,您已經有了Identifiable&Identifier接口,這意味着每個Identifiable(例如book,pdf等)都必須具有一些Identifier(例如ISBN,bookNumber等)。

現在,您可以使用Book作為Identifiable和ISBN作為Identifier來實現此頂層層次結構。 這將是您的實施層。

然后,您為泛型中提到的Identifiable創建DataProvider接口。 它的get方法將以標識符作為參數,即如果DataProvider用於Book,則其get方法將用於ISBN。

現在,您在此處使用BookDataProvider實現DataProvider。 在此類中,您不會將ISBN作為參數,而是將標識符作為參數。 您可以在其中傳遞ISBN,因為它是一個標識符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM