0

ジェネリックスを使用して、インターフェイスを希望どおりに機能させるのに問題があります。

さまざまなオブジェクトのデータアクセスを処理するためのCRUDスタイルのインターフェイスがあります。Comparable<?>オブジェクトにはさまざまなタイプの識別子がある可能性があるため、識別子でオブジェクトを取得するために使用されます。

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

ここで、アクセスする必要のあるそのような(考案された)オブジェクトの1つを想像してみてください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ごとにインターフェイスを導入し、実装して、と入力しますが、の署名を取得できません。BookDataProviderDataProvider<T extends Identifiable<?>>get(ISBN)

DataProvider理想的には、タイプパラメータを1つだけに制限したいと思います。私は他のアプローチにもオープンです。ありがとう。

4

1 に答える 1

0

アプリケーション固有のゲッターメソッドでパラメーターとしてComparableを使用することは適切ではありません。理想的には、getメソッドはComparableでは機能しないはずです。ISBNなどの特定のタイプ専用です。したがって、比較可能なジェネリックスに苦労する代わりに、そのような識別子の共通インターフェースを選択することをお勧めします。

部分的なオプションから2番目のアプローチを取り、1つのソリューションを作成しましょう。以下は私が提案するコードです。

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

}

現在、このアプローチは真に一般的です。これは、最上位レベルにIDと識別子のインターフェイスがあるためです。つまり、すべての識別子(book、pdfなど)にはID(ISBN、bookNumberなど)が必要です。

ここで、この最上位の階層を、Bookを識別子として、ISBNを識別子として実装します。これが実装レイヤーになります。

次に、ジェネリックスで言及されている識別可能なデータプロバイダーインターフェイスを作成します。そのgetメソッドはパラメーターとして識別子を持ちます。つまり、DataProviderがBook用の場合、そのgetメソッドはISBN用になります。

ここで、BookDataProviderを使用してDataProviderを実装します。このクラスでは、パラメーターとしてISBNを取得しませんが、代わりにパラメーターとして識別子を使用します。識別子であるため、ISBNを渡すことができます。

于 2012-11-16T08:54:56.173 に答える