17

それでは、文字列のリストと、Hamcrest マッチャーを受け取りmatches()、提供されたマッチャーのメソッドの結果を返す関数を用意しましょう。

public boolean matchIt(final Matcher<? super List<String>> matcher) {
    final List<String> lst = obtainListFromSomewhere();
    return matcher.matches(lst);
}

ここまでは順調ですね。今、私は簡単に呼び出すことができます:

matchIt(empty());
matchIt(anything());
matchIt(hasItem("item"));
matchIt(everyItem(equalToIgnoringCase("item")));

...これらのファクトリ静的メソッドはすべて、メソッド シグネチャに適合するマッチャーを生成するためMatcher<? super List<String>>です。

ただし、オブジェクトの Iterable を受け入れるマッチャーもmatchIt()メソッドで受け入れられるべきだと思います。

matchIt(everyItem(anything()));

だから私は単純にmatchIt()メソッドの署名を変更しました:

public boolean matchIt(final Matcher<? super List<? super String>> matcher);

しかし、それはまったく機能しません。を受け入れないだけでなくeveryItem(anything())、以前の正しいeveryItem(equalToIgnoringCase("item"))ことわざ (1.7.0_05 コンパイラ バージョン)も受け入れません。

actual argument Matcher<Iterable<String>> cannot be converted to Matcher<? super List<? super String>> by method invocation conversion

何?ここで何が問題なのですか?matchIt()メソッドの署名ですか、それともeveryItem()Hamcrest の署名が間違って設計されていますか? それとも、Java ジェネリック システムが修復不可能なだけなのでしょうか? コメントありがとうございます!

EDIT @rlegendi ここでの私の意図は、クライアントがリストに関する述語を追加および実行するためのインターフェースを提供することです。それがmatchIt()方法です。このシナリオでは、呼び出しmatchIt(anything())が理にかなっています。クライアントは、リストが何かであるかどうかを知りたがっています。呼び出しmatchIt(empty())は、クライアントがリストが空かどうかを知りたがっていることを意味します。matchIt(everyItem(equalToIgnoringCase("item")))との場合はその逆ですmatchIt(hasItem("item"))

ここでの私の目標は、可能な限り最良の matchIt()メソッド シグネチャを作成することです。これMatcher<? super List<String>>までのすべてのシナリオで問題なく動作します。ただし、クライアントMatcher<Iterable<Object>>もマッチャーを追加できるようにする必要があると思います (たとえばmatchIt(everyItem(notNullValue())、ここでは完全に理にかなっています。クライアントは、リストのすべての String 項目が null でないかどうかを知りたいと考えています)。

ただし、正しい署名が見つからないため、matchIt(Matcher<? super List<? super String>>)機能しませんeveryItem(notNullValue());

Hamcrest 1.3 を使用しています。

編集2:

私は根本的な誤解を見つけたと思います。

everyItem(anything())式はタイプ のオブジェクトを返しますMatcher<Iterable<Object>>。だから簡単にできるMatcher<Iterable<Object>> m = everyItem(anything());

しかし、私が理解していないのは、なぜ私ができないのかということですMatcher<? super List<? super String>> m1 = m;。そうでMatcher<Iterable<Object>>はないようですがMatcher<? super List<? super String>>、理由はわかりません。

私もできませんMatcher<? super List<?>> m1 = m;Matcher<Iterable<Object>>ではありませんMatcher<? super List<?>>か?なんで?

4

2 に答える 2

4

ただし、オブジェクトの Iterable を受け入れるマッチャーは、 matchIt() メソッドでも受け入れられるべきだと思います

いいえ、それは正しくありません。の代わりに、とりあえずIterable考えてみましょう。Listしたがって、 がMatcher<List<Object>>あり、そのmatchesメソッドは を受け取りますList<Object>。さて、これにはList<String>? いいえ。その理由はおそらく既にご存じでしょうObject。リストに型のオブジェクトを追加できるからです。

さて、クラスに名前を付ける際に、メソッドが読み取り専用であり、それに与えられたリストを変更しないことMatcherを期待していることを私は知っています。matchesただし、その保証はありません。実際にリストに何も追加しない場合、マッチャーの正しいタイプは になります。これにより、(1)メソッドは 以外のものをリストに追加Matcher<List<?>>できなくなり、(2)メソッドは のリストを取得できるようになります。いかなるタイプ。matchesnullmatches

あなたの現在のメソッド署名public boolean matchIt(final Matcher<? super List<String>> matcher)はすでにMatcher<List<?>>(またはMatcher<Iterable<?>>) を許可していると思います。

于 2012-10-21T22:02:08.797 に答える
1

これで何か問題がありますか?

public boolean matchIt(final Matcher<? extends Iterable<String>> matcher);
于 2012-10-22T00:06:53.020 に答える