Generics Hell: Hamcrest Matcher als Methodenparameter
Lassen Sie uns also eine Liste von Zeichenfolgen und eine Funktion erstellen, die einen Hamcrest-Matcher verwendet und ein Ergebnis der zurückgibtmatches()
Methode des bereitgestellten Matchers:
public boolean matchIt(final Matcher<? super List<String>> matcher) {
final List<String> lst = obtainListFromSomewhere();
return matcher.matches(lst);
}
So weit, ist es gut. Jetzt kann ich einfach anrufen:
matchIt(empty());
matchIt(anything());
matchIt(hasItem("item"));
matchIt(everyItem(equalToIgnoringCase("item")));
... da alle diese fabrikstatischen Methoden einen Matcher erzeugen, der zur Methodensignatur passtMatcher<? super List<String>>
.
Ich bin jedoch der Meinung, dass ein Matcher, der eine Iterable von Objekten akzeptiert, von der akzeptiert werden solltematchIt()
Methode auch:
matchIt(everyItem(anything()));
Also habe ich das naiv geändertmatchIt()
Methodensignatur:
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
Aber es funktioniert überhaupt nicht. Nicht nur, dass es nicht akzeptierteveryItem(anything())
, es akzeptiert nicht einmal die zuvor korrekteneveryItem(equalToIgnoringCase("item"))
Sprichwort (1.7.0_05 Compiler-Version):
actual argument Matcher<Iterable<String>> cannot be converted to Matcher<? super List<? super String>> by method invocation conversion
Was zum? Also, was ist hier los? Ist es dermatchIt()
Methodensignatur oder ist dieeveryItem()
Hamcrest Signatur falsch gestaltet? Oder ist es nur das Java Generics System, das nicht mehr repariert werden kann? Vielen Dank für Ihre Kommentare!
BEARBEITEN @rlegendi Meine Absicht ist es, dem Client eine Schnittstelle zum Hinzufügen und Ausführen von Prädikaten zu der Liste zur Verfügung zu stellen. Das ist dasmatchIt()
Methode. BerufungmatchIt(anything())
In diesem Szenario macht es Sinn, der Kunde möchte wissen, ob die Liste etwas ist. BerufungmatchIt(empty())
bedeutet, dass der Kunde wissen möchte, ob die Liste leer ist. Umgekehrt fürmatchIt(everyItem(equalToIgnoringCase("item")))
undmatchIt(hasItem("item"))
.
Mein Ziel hier ist es, eine zu habenBeste matchIt()
Methodensignatur möglich. DasMatcher<? super List<String>>
Funktioniert gut für alle vorherigen Szenarien. Ich bin jedoch der Meinung, dass der Kunde hinzufügen darfMatcher<Iterable<Object>>
auch Matcher (zum BeispielmatchIt(everyItem(notNullValue())
Sinnvoll ist hier, dass der Client wissen möchte, ob jeder String-Eintrag der Liste nicht null ist.
Ich kann jedoch nicht die richtige Signatur finden.matchIt(Matcher<? super List<? super String>>)
funktioniert nicht füreveryItem(notNullValue());
Ich benutze Hamcrest 1.3.
EDIT 2:
Ich glaube, ich habe mein Grundmissverständnis gefunden.
DaseveryItem(anything())
Ausdruck gibt ein Objekt vom Typ zurückMatcher<Iterable<Object>>
. So kann ich das leicht machenMatcher<Iterable<Object>> m = everyItem(anything());
Was ich jedoch nicht verstehe, ist, warum ich es nicht kannMatcher<? super List<? super String>> m1 = m;
. Es scheint, dassMatcher<Iterable<Object>>
ist nichtMatcher<? super List<? super String>>
aber ich verstehe nicht warum.
Ich kann es nicht einmal tunMatcher<? super List<?>> m1 = m;
. Matcher<Iterable<Object>>
ist nichtMatcher<? super List<?>>
? Warum?