我有方法命名参数
def test(String a, String b) { }
,我想有一个动态的参数映射到调用它。 我总是尽管这
test(['1','2']); //valid call
也
test([a:'1',b:'2']); //=> does not work
会工作。但事实并非如此。所以我记得the spread operator,但不能得到它的工作....
有没有一种方法来调用像上面那种方法与某种地图作为参数,而不是单个参数?
我有方法命名参数
def test(String a, String b) { }
,我想有一个动态的参数映射到调用它。 我总是尽管这
test(['1','2']); //valid call
也
test([a:'1',b:'2']); //=> does not work
会工作。但事实并非如此。所以我记得the spread operator,但不能得到它的工作....
有没有一种方法来调用像上面那种方法与某种地图作为参数,而不是单个参数?
也许我错过了一些东西,但我不认为Groovy已经命名了参数。有discussions和proposals,但我不知道任何官方。
对于您的情况,我认为地图传播可能帮助,但不是在任何情况下。一旦获得值,它遵循其中的地图值声明的顺序:
def test(String a, String b) { "a=$a, b=$b" }
def test(Map m) { test m*.value }
assert test(a: "aa", b:"bb") == "a=aa, b=bb"
assert test(b: "aa", a:"bb") != "a=aa, b=bb" // should be false :-(
assert test(b: "ccc", a:"ddd") == "a=ddd, b=ccc" // should have worked :-(
对于类,我建议Groovy's as operator?
@groovy.transform.CompileStatic
class Spread {
class Person {
String name
BigDecimal height
}
def method(Person p) {
"Name: ${p.name}, height: ${p.height}"
}
def method(Map m) { method m as Person }
static main(String[] args) {
assert new Spread().method(name: "John", height: 1.80) ==
"Name: John, height: 1.80"
}
}
感谢名单向Will P的评论,我发现它适合我的问题的解决方案:
如果我定义一个参数没有一个类型,我可以在所有种类型,其中包含HashMap通过。和Groovy变成像a:'h',b:'i'
构建自动地进入一个HashMap
def test(myParams, Integer i) {
return myParams.a + myParams.b
}
assert test(a:'h',b:'i',5) == test(b:'i',a:'h',5)
assert test([a:'h',b:'i'],5) == test(b:'i',a:'h',5)
test('h','i',5); //still throws an exception
这样一来,我可以使用单一的命名参数,但可以使用地图呢!
我以为你在寻找类似python命名参数的东西(http://davedash.com/2007/12/21/python-named-arguments-pure-genius/)。很高兴你找到了你的解决方案,无论如何:-) – Will
命名参数支持非常灵活,但文档有点薄。以下是我发现的一些规则。 请注意,我想是的参数(在方法中声明)和args用户明确的(传递给方法调用)
(a: "aa")
足够好,你不需要([a: "aa"])
x
)args=[:]
使 命名ARGS可选的,但是这并不工作得很好,如果你有 其他可选参数(参见下面的例子最后)下面是一些例子: 】这个params不需要键入,但我已经添加类型的清晰度。
// this method has a map args to capture all named args
// and non-named (ordered) args String s, int n, and int x
// x has a default value so is optional
// the map (here untyped) to capture the nameed args MUST COME FIRST
def m(Map args=[:], String s, int n, int x=1)
{
println "s:$s n:$n x:$x, args:$args"
}
//1: pass in named args first, then ordered
m(a: "aa", b: 3, "ss", 44, 5) // s:s n:44 x:5, args:[a:aa, b:3]
//2: ordered args first - named args last (same result)
m("ss", 44, 5, a: "aa", b: 3) // s:s n:44 x:5, args:[a:aa, b:3]
//3: bring the first ordered arg (s) to the start (same result)
m("ss", a: "aa", b: 3, 44, 5) // s:s n:44 x:5, args:[a:aa, b:3]
//4: stick the ordered arg n in the middle of the named args (same result!)
m("ss", a: "aa", 44, b: 3, 5) // s:s n:44 x:5, args:[a:aa, b:3]
//5: mix the ordered args in with the named and SKIP the arg x with default value (x=1)
m(a: "aa", "ss", b: 3, 44) // s:ss n:44 x:1, args:[a:aa, b:3]
//6: ordered arg n first - so in the wrong order (Fail!)
//m(44, "ss", a: "aa", b: 3, 5) //MissingMethodException: No signature .. of .. m() .. applicable for
// argument types: (java.util.LinkedHashMap, java.lang.Integer, java.lang.String, java.lang.Integer)
// values: [[a:aa, b:3], 44, ss, 5]
//7: no named args: Fails! (change signature to add default: Map args=[:] and it will succeed with: s:ss n:44 x:1, args:[:]
m("ss", 44) // ...No signature ... applicaple ... types (java.lang.String, java.lang.Integer)
//8: no named args: Fails! (even with default map in signature this fails!)
m("ss", 44, 5) // ...No signature ... applicaple ... types (java.lang.String, java.lang.Integer, java.lang.Integer)
我不知道常规支持的命名的参数现在...您的例子并不在我的Groovy的2.0.6 – Will
您正在工作(部分)右 - 我已经更新了我的问题。部分原因是我的例子不对,但groovy支持命名参数。 http://mrhaki.blogspot.de/2009/09/groovy-goodness-named-parameters-are.html - 嘿,我想这是我的问题的解决方案... – rdmueller