Generics hell: hamcrest matcher como um parâmetro de método
Então, vamos ter uma lista de seqüências de caracteres e uma função que leva um matcher Hamcrest e retorna um resultado domatches()
método do correspondente fornecido:
public boolean matchIt(final Matcher<? super List<String>> matcher) {
final List<String> lst = obtainListFromSomewhere();
return matcher.matches(lst);
}
Por enquanto, tudo bem. Agora eu posso ligar facilmente:
matchIt(empty());
matchIt(anything());
matchIt(hasItem("item"));
matchIt(everyItem(equalToIgnoringCase("item")));
... uma vez que todos esses métodos estáticos de fábrica produzem um correspondente que se ajusta à assinatura do métodoMatcher<? super List<String>>
.
No entanto, acredito que um matcher que aceita um objeto Iterable deve ser aceito pelomatchIt()
método também:
matchIt(everyItem(anything()));
Então eu ingenuamente mudei omatchIt()
assinatura do método:
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
Mas isso não funciona de todo. Não só não aceitaeveryItem(anything())
, nem aceita o correto anteriormenteeveryItem(equalToIgnoringCase("item"))
dizendo (versão do compilador 1.7.0_05):
actual argument Matcher<Iterable<String>> cannot be converted to Matcher<? super List<? super String>> by method invocation conversion
O que? Então, o que há de errado aqui? É omatchIt()
assinatura do método ou é oeveryItem()
Assinatura de Hamcrest projetada erroneamente? Ou é apenas o sistema genérico Java que está além do reparo? Muito obrigado por seus comentários!
EDITAR @rlegendi minha intenção aqui é fornecer uma interface para o cliente adicionar e executar predicados sobre a lista. Essa é amatchIt()
método. ChamandomatchIt(anything())
faz sentido nesse cenário, o cliente quer saber se a lista é alguma coisa. ChamandomatchIt(empty())
significa que o cliente quer saber se a lista está vazia. Vice-versa paramatchIt(everyItem(equalToIgnoringCase("item")))
ematchIt(hasItem("item"))
.
Meu objetivo aqui é ter ummelhor matchIt()
assinatura de método possível. oMatcher<? super List<String>>
funciona bem para todos os cenários anteriores. No entanto, acredito que o cliente deve ter permissão para adicionarMatcher<Iterable<Object>>
correspondentes (por exemplomatchIt(everyItem(notNullValue())
faz sentido aqui, o cliente quer saber se todos os itens da lista não são nulos).
No entanto, não consigo encontrar a assinatura certamatchIt(Matcher<? super List<? super String>>)
não funciona paraeveryItem(notNullValue());
Eu uso o Hamcrest 1.3.
EDIT 2:
Acredito ter encontrado meu mal-entendido de raiz.
oeveryItem(anything())
expressão retornar um objeto do tipoMatcher<Iterable<Object>>
. Então eu posso fazer facilmenteMatcher<Iterable<Object>> m = everyItem(anything());
No entanto o que eu não entendo é porque eu não posso fazerMatcher<? super List<? super String>> m1 = m;
. Parece queMatcher<Iterable<Object>>
não éMatcher<? super List<? super String>>
mas eu não entendo porque.
Eu não posso nem fazerMatcher<? super List<?>> m1 = m;
. Matcher<Iterable<Object>>
não éMatcher<? super List<?>>
? Por quê?