Groovy将把所有命名参数收集到一个map中,并将其作为第一个参数传递给一个方法。这看起来很整洁,但在尝试使其工作后,它似乎真的无法使用。
所以问题是这样一个方法:
def method(paramMap, specificVar1 = 7, specificVar2 = 14)
当你用类似这样的方法调用这个方法时:
method(12, extraValue: "hello")
你会得到你所期望的
assert 12 == specificVar1
assert 14 == specificVar2
assert [extraValue:"hello"] == paramMap
不错,有道理。问题是,如果你假设Map
参数是可选的,那么你最终会得到这样的值:
method(12)
assert paramMap == 12
assert specificVar1 == 7 // default values
assert specificVar2 == 14
标量应该进入specificVar--而不是map。如果我在方法中专门输入map:
def method(Map paramMap, specificVar1 = 7, specificVar2 = 14)
那么method(12, extraValue: "hello")
就像以前一样工作,但是method(12)
抛出一个ClassCastException
。这个好像不太好用有没有办法让Map
“粘滞”,这样如果没有Map
参数,它就只是空的?
注意事项:
十年后,我又重新审视了这一点,因为有2500个浏览量的通知。公认的答案重载解决方案是完美的。基本上是第二种方法:
def method(specificVar1 = 7, specificVar2 = 14)
{
method([:],specificVar1, specificVar2)
}
似乎对我所有的测试用例都很好,不管有没有默认值。
如果我想进一步研究这个问题,我可能会尝试找出如何为我喜欢从repl运行的一堆方法综合生成这样的重载。
1条答案
按热度按时间hyrbngr71#
设置参数的默认值会创建重载方法,这些方法的组合是从左到右的,因此,很难创建
method(12)
,也很难传递map条目。方法
def method(paramMap, specificVar1=7, specificVar2=14)
将生成以下方法:以及一个带有map参数的全类型方法:
将生成以下方法:
(No适用于
method(12)
方法)。此外,传递给该方法的条目将被收集并插入到第一个 map 参数中。以下方法:
生成:
因此,
method4 12, a:'b'
失败:所以,不,我不认为你可以做你想用Map:-)。
方案一:
如果你是一个纯动态的解决方案,你可以使用一个单一的map参数:
方案二(更新):
您可以创建一个类来表示参数。使用强制到对象中的Map是静态可编译的,并且是一种语法糖。
方案三:
重载方法。
map version方法不能有默认参数,否则两个方法都会生成一个无参数的
method6
,并且会发生冲突。