4

SearchResponse、SearchResponseHit、SpecialSearchResponse(SearchResponseを拡張)およびSpecialSearchResponseHit(SearchResponseHitを拡張)のクラスがあります。

SearchResponseは次のようになります。

public class SearchResponse implements Iterable<SearchResponseHit> {

    [...]

    public Iterator<SearchResponseHit> iterator() {
        return searchResponseHits.iterator();
    }
}

これにより、次のようにforeachループでSearchResponseのインスタンスを使用できるようになります。

for (SearchResponseHit hit : mySearchResponse) {
    [...]
}

さて、私がやりたいのは、方法がわからないのですが、SpecialSearchResponseのインスタンスがあるときにこのコードをコンパイルすることです。

for (SpecialSearchResponseHit specialHit : mySpecialSearchResponse) {
    [...]
}

これにより、次のコンパイラエラーが発生します。

Type mismatch: cannot convert from element type SearchResponseHit to SpecialSearchResponseHit

このコードをSpecialSearchResponseに追加しようとすると、次のようになります。

public Iterator<SpecialSearchResponseHit> iterator() {
    [...]
}

...エラーが発生します:

The return type is incompatible with Iterable<SearchResponseHit>.iterator()

SearchResponseのメソッドを次のように変更してみました。

    public Iterator<? extends SearchResponseHit> iterator() {
        return searchResponseHits.iterator();
    }

...しかし、これは私にエラーを与えます:

The return type is incompatible with Iterable<SearchResponseHit>.iterator()

次に、クラス定義を次のように変更してみました。

public class SearchResponse implements Iterable<? extends SearchResponseHit>

...しかし、これは私にこのエラーを与えます:

    The type SearchResponse cannot extend or implement Iterable<? extends SearchResponseHit>. A supertype may not specify any wildcard

これを解決するための最良の(そして最も美しい)方法は何ですか?または、foreachメソッド(およびバックグラウンドでIterableインターフェイスを使用する他の関数)をスキップしてgetSpecialIterator()メソッドを記述してから、イテレーターを直接使用する必要がありますか?

よろしく/J

4

2 に答える 2

9

1 つの方法は、次の方法でさまざまなクラスを宣言することです。

public class SearchResponse<T  extends SearchResponseHit> implements Iterable<T> {
    List<T> searchResponseHits;

    public Iterator<T> iterator() {
        return searchResponseHits.iterator();
    }
}

public class SearchResponseHit {}

public class SpecialSearchResponse extends SearchResponse<SpecialSearchResponseHit> {}
public class SpecialSearchResponseHit extends SearchResponseHit {}

そうすれば、次のように呼び出すことができます。

    SearchResponse<SearchResponseHit> sr = new SearchResponse<SearchResponseHit>();
    for (SearchResponseHit h : sr) {}

    SpecialSearchResponse ssr = new SpecialSearchResponse();
    for (SpecialSearchResponseHit h : ssr) {}

しかし、それはクラスにジェネリックを導入し、もはやSearchResponse単純に宣言することはできませSearchResponse sr = new SearchResponse()ん (警告とキャストなしで)。


更新
コメントに続いて、代わりに、ジェネリックボイラープレートを含む共通のスーパークラスを作成することもできます.クラスのユーザーがそれを見ないように、それを抽象化し、パッケージを非公開にすることができます:

abstract class AbstractSearchResponse<T  extends SearchResponseHit> implements Iterable<T>{
    List<T> searchResponseHits;

    public Iterator<T> iterator() {
        return searchResponseHits.iterator();
    }
}

public class SearchResponse extends AbstractSearchResponse<SearchResponseHit> { }
public class SpecialSearchResponse extends AbstractSearchResponse<SpecialSearchResponseHit> {}

これで、必要に応じて 2 つの子を呼び出すことができます。

SearchResponse sr = new SearchResponse();
for (SearchResponseHit h : sr) {}

SpecialSearchResponse ssr = new SpecialSearchResponse();
for (SpecialSearchResponseHit h : ssr) {}
于 2012-06-07T14:51:09.793 に答える