Jan*_*dek 17 java generics hamcrest
所以,让我们有一个字符串列表和一个带有Hamcrest匹配器的函数,并返回matches()
提供的匹配器的方法结果:
public boolean matchIt(final Matcher<? super List<String>> matcher) {
final List<String> lst = obtainListFromSomewhere();
return matcher.matches(lst);
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.现在我可以轻松打电话:
matchIt(empty());
matchIt(anything());
matchIt(hasItem("item"));
matchIt(everyItem(equalToIgnoringCase("item")));
Run Code Online (Sandbox Code Playgroud)
...因为所有这些工厂静态方法都生成一个适合方法签名的匹配器Matcher<? super List<String>>
.
但是,我相信该matchIt()
方法也应该接受一个接受Iterable对象的匹配器:
matchIt(everyItem(anything()));
Run Code Online (Sandbox Code Playgroud)
所以我天真地改变了matchIt()
方法签名:
public boolean matchIt(final Matcher<? super List<? super String>> matcher);
Run Code Online (Sandbox Code Playgroud)
但它根本不起作用.它不仅不接受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
Run Code Online (Sandbox Code Playgroud)
什么?那么这里有什么问题?它是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<?>>
吗?为什么?
但是,我相信接受 Iterable 对象的匹配器也应该被 matchIt() 方法接受
不,那是不正确的。Iterable
我们List
暂时考虑一下。所以你有 a Matcher<List<Object>>
,它的matches
方法需要 a List<Object>
。现在,这需要一个吗List<String>
?不。您可能已经知道原因了——因为它可以将一个类型的对象添加Object
到列表中。
现在,我知道在命名类时Matcher
,您希望该matches
方法是只读的,并且不会改变给定它的列表。然而,这并不能保证。如果它确实没有向列表中添加任何内容,则匹配器的正确类型将是Matcher<List<?>>
,其中 (1) 不允许该matches
方法将任何内容添加到列表中,除了null
,并且 (2) 将允许该matches
方法采用以下列表:任何类型。
我相信您当前的方法签名public boolean matchIt(final Matcher<? super List<String>> matcher)
已经允许Matcher<List<?>>
(或Matcher<Iterable<?>>
)。
归档时间: |
|
查看次数: |
3477 次 |
最近记录: |