Generics hell: hamcrest matcher jako parametr metody

Zróbmy więc listę łańcuchów i funkcję, która pobiera matcher Hamcresta i zwraca wynikmatches() metoda dostarczonego matchera:

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

Jak na razie dobrze. Teraz mogę łatwo zadzwonić:

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

... ponieważ wszystkie te fabryczne metody statyczne wytwarzają urządzenie dopasowujące do podpisu metodyMatcher<? super List<String>>.

Uważam jednak, że urządzenie akceptujące obiekty Iterable powinno zostać zaakceptowane przezmatchIt() metoda:

matchIt(everyItem(anything()));

Więc naiwnie zmieniłemmatchIt() podpis metody:

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

Ale to w ogóle nie działa. Nie tylko nie akceptujeeveryItem(anything()), nie akceptuje nawet poprawnego poprzednioeveryItem(equalToIgnoringCase("item")) mówiąc (wersja kompilatora 1.7.0_05):

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

Co? Więc co tu jest nie tak? Czy to jestmatchIt() podpis metody lub jesteveryItem() Źle zaprojektowany podpis Hamcresta? Czy może po prostu nie można naprawić systemu generycznego Java? Wielkie dzięki za komentarze!

EDYTUJ @rlegendi Moim zamiarem jest zapewnienie interfejsu dla klienta do dodawania i wykonywania predykatów dotyczących listy. To jestmatchIt() metoda. PowołaniematchIt(anything()) ma sens w tym scenariuszu, klient chce wiedzieć, czy lista jest czymś. PowołaniematchIt(empty()) oznacza, że ​​klient chce wiedzieć, czy lista jest pusta. Odwrotnie dlamatchIt(everyItem(equalToIgnoringCase("item"))) imatchIt(hasItem("item")).

Moim celem jest posiadanieNajlepiej matchIt() możliwy podpis metody. TheMatcher<? super List<String>> działa dobrze dla wszystkich poprzednich scenariuszy. Uważam jednak, że klient powinien mieć możliwość dodaniaMatcher<Iterable<Object>> również zapałki (na przykładmatchIt(everyItem(notNullValue()) ma tu sens, klient chce wiedzieć, czy każdy element String na liście nie jest pusty).

Jednak nie mogę znaleźć właściwego podpisu,matchIt(Matcher<? super List<? super String>>) nie działa dlaeveryItem(notNullValue());

Używam Hamcrest 1.3.

EDYCJA 2:

Wierzę, że znalazłem swoje nieporozumienie.

TheeveryItem(anything()) wyrażenie zwraca obiekt typuMatcher<Iterable<Object>>. Więc mogę zrobić łatwoMatcher<Iterable<Object>> m = everyItem(anything());

Jednak nie rozumiem, dlaczego nie mogę tego zrobićMatcher<? super List<? super String>> m1 = m;. Wygląda na to żeMatcher<Iterable<Object>> nie jestMatcher<? super List<? super String>> ale nie rozumiem dlaczego.

Nawet nie mogę tego zrobićMatcher<? super List<?>> m1 = m;. Matcher<Iterable<Object>> nie jestMatcher<? super List<?>>? Czemu?

questionAnswers(2)

yourAnswerToTheQuestion