0

我无法让接口按照我希望使用泛型的方式工作。

我有一个 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)编译的最简单方法是什么?

我提出了几个部分解决方案,但我不确定是否是最优的:

  • 键入DataProvideras DataProvider<T, I extends Comparable<I>>,但这会增加一个额外的类型参数。
  • 根据这个相关帖子介绍一个Identifiable接口,实现它,然后键入as ,但是我没有实现.BookDataProviderDataProvider<T extends Identifiable<?>>get(ISBN)

理想情况下,我想限制DataProvider只有一个类型参数。我也对其他方法持开放态度。谢谢。

4

1 回答 1

0

在应用程序特定的 getter 方法中使用 Comparable 作为参数是不合适的。理想情况下,您的 get 方法不应该适用于任何 Comparable。它仅适用于 ISBN 等特定类型。所以我建议不要为 Comparable 泛型而苦苦挣扎,而是为此类标识符寻求通用接口。

让我们从您的部分选项中采用第二种方法并创建一个解决方案。下面是我建议的代码。

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 方法将Identifier 作为参数,即如果DataProvider 用于Book,那么它的get 方法将用于ISBN。

现在在这里您使用 BookDataProvider 实现 DataProvider。在此类中,您不会将 ISBN 作为参数,而是将 Identifier 作为参数。您可以在其中传递 ISBN,因为它是一个标识符。

于 2012-11-16T08:54:56.173 回答