使用documented mixture of named and positional arguments(或具有默认值的args),如何在不指定任何命名参数的情况下调用方法?
我正在尝试扩展现有的共享方法而不会破坏其他人的代码,这种方法看起来很有希望,但以下示例失败:
def test(Map args, some, thing='default value'){
"$some $thing";
}
//good - adding any named parameter works
//test('yet', 'another good', anything:'notneeded');
//but not specifying named parameter fails
test('this', 'fails');
我无法找到有关此行为的文档,它看起来很奇怪。
这取决于现有方法签名的外观。假设您有一个带有1个参数的现有方法,如下所示:
def test(String input) { ... }
如果您想添加传递一个额外位置参数的功能,您只需添加一个重载:
def test(String input, String output) { ... }
如果要添加可选的命名参数,可以添加此重载:
def test(Map namedArgs, String input) { ... }
如果你调用“test('')”,它将运行原始方法。 “test('one','two')”将运行secobd版本。 “测试('一个',两个:'两个')”将运行第三个。
如果要支持2个位置参数和一个或多个命名参数,可能需要添加第4个重载。
通过设置map参数的默认值,可以使方法的命名参数成为可选参数。例如:
def test(Map args = [:], some, thing='default value'){
"$some $thing";
}
这将允许任何这些调用成功:
test('some value')
test('some value', 'thing value')
test('some value', extra1: 'e1', extra2: 'e2')
test(extra: 'val', 'some value', 'thing value')
groovy解析器需要一些信息才能确定要执行的方法。
所以,如果你写:
test('yet', 'another good', anything:'notneeded')
这被翻译成:
test([anything:'notneeded'], 'yet', 'another good')
即所有命名参数样式参数(带冒号)都放入一个映射并放在参数列表的开头。之后放置所有剩余参数。
所以Groovy现在寻找签名test(Map, String, String)
并正确找到你的方法。
如果没有命名参数,则不会发生此转换,签名将为test(String, String)
,它没有匹配方法。
因此,解决方案是创建一个与没有命名参数的调用匹配的附加方法:
def test(some, thing='default value'){
test([:], some, thing)
}
这样,支持命名和非命名调用。