今天当我发现我可以使用GroovyBeans点符号从地图列表中获取属性时,我偶然发现它看起来像一个小的Groovy魔法:
List list = [[a: 1, b: 2], [c: 3, d: 4]]
assert list.b == [2, null]
如果返回的值在上面的示例中仅为2,那么这对我的用例非常有用。我认为覆盖getAt方法会做的伎俩,事实上这是有效的(在这个例子中,如果有超过1个非null结果,它将返回第一个是OK)
List.metaClass.getAt = { String s -> return delegate.findAll({ Map m -> m.get(s) }).get(0).get(s) }
List list = [[a: 1, b: 2], [c: 3, d: 4]]
assert list.getAt("b") == 2
但是......如果我使用点表示法,被调用的方法是而不是 getAt(String)
List.metaClass.getAt = { String s -> return delegate.findAll({ Map m -> m.get(s) }).get(0).get(s) }
List list = [[a: 1, b: 2], [c: 3, d: 4]]
assert list.b == 2 // Assertion failed
我无法找到用点符号调用的方法......有人有任何线索吗?
你可能想知道我为什么要在明确调用方法时使用点符号给我我想要的东西,但事实上这是我编写的DSL的一部分所以我可以很容易地向正在进行的人解释使用它是什么例如
current.processDate
但很难解释他们必须做的事情
current[0].processDate ?: current[1].processDate
甚至
current.getAt("processDate")
提前致谢。
我现在认为这样做是不可能的。我逐步完成了所有代码,实际获取列表中地图值的代码片段并累积了这些值
DefaultGroovyMethods
private static List getAtIterable(Iterable coll, String property, List<Object> answer)
我不能像这样覆盖它
DefaultGroovyMethods.metaClass.static.getAtIterable = {
coll, property, answer ->
def find = coll.find { it != null }
return find
}
我还试图覆盖点符号
中调用的第一个方法AbstractCallSite
public Object callGetProperty(Object receiver) throws Throwable {
return this.acceptGetProperty(receiver).getProperty(receiver);
}
像这样:
AbstractCallSite.metaClass.callGetProperty = {
Object receiver ->
if ( !(receiver instanceof ArrayList)){
return delegate.callGetProperty(receiver)
}
return "SOMETHING"
}
所以也许是时候把它叫做退出了?