Итак, пусть список строк и функция, которая принимает совпадение 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")));
... так как все эти статические методы factory создают набор, который соответствует сигнатуре метода Matcher<? super List<String>>
.
Однако, я считаю, что метод-совместитель, который принимает итерацию объектов, должен быть принят также с помощью метода matchIt()
:
matchIt(everyItem(anything()));
Итак, я наивно изменил подпись метода matchIt()
:
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
Но это совсем не работает. Он не только не принимает everyItem(anything())
, он даже не принимает ранее правильную версию everyItem(equalToIgnoringCase("item"))
say (версия компилятора 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 не подлежит ремонту? Большое спасибо за ваши комментарии!
ИЗМЕНИТЬ
@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 списка нулевым).
Однако я не могу найти правильную подпись, 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<?>>
? Почему?