所以,让我们有一个字符串列表和一个带有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项是否都为空)。 / p>
但是我找不到合适的签名,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<?>>
?为什么呢?
答案 0 :(得分:4)
但是,我相信一个接受Iterable对象的匹配器 应该被matchIt()方法接受
不,这不正确。我们暂时不考虑Iterable
,而是考虑List
。因此,您有Matcher<List<Object>>
,其matches
方法需要List<Object>
。现在,这会花费List<String>
吗?不。您可能已经知道原因 - 因为它可以在列表中添加Object
类型的对象。
现在,我知道在命名类Matcher
时,您希望matches
方法是只读的,而不是改变给定的列表。但是,不能保证这一点。如果它确实没有向列表中添加任何内容,则匹配器的正确类型为Matcher<List<?>>
,其中(1)不允许matches
方法向列表添加任何内容,{{1}除外}和(2)将允许null
方法获取任何类型的列表。
我相信您当前的方法签名matches
已经允许public boolean matchIt(final Matcher<? super List<String>> matcher)
(或Matcher<List<?>>
)。
答案 1 :(得分:1)
这有什么不对吗?
public boolean matchIt(final Matcher<? extends Iterable<String>> matcher);