Groovy 的多重赋值和方法的多返回值

追溯到刚开始学习 Groovy 还是在  2008 年,距今 2018 年有九年半余,曾记下几篇 Groovy 的日志。那时学习 Groovy 并无明确的目的,只因它是脚本语言, 可用来快速验证 Java API。曾经 BeanShell 芸花一现,JRuby 和 Jython 总是别人家的语言照搬而来的。而 Scala,Nashorn(jjs), JShell 更是后来的事,唯有 Groovy 写起来很亲切,完全不懂 Groovy 都没关系,直接上 Java。

现如今之所以重新勾搭上了 Groovy 是因为它仍然坚挺着,在 SoupUI(ReadyAPI) 和 Jenkins 中获得了重视,倒不是因为 Gradle。先前 Groovy 在 Spring 框架中的地位估计要被如今的 Kotlin 取而代之。

好了,回顾完后进入正题,关于 Groovy 如何进行多重赋值,以及延伸到方法返回多个值的情形。这里所说的多重赋值不是指用连等号来同时赋为一个值,

def a = b = c = 100   //不是说的这个

而是指同时对多个变量一步到位的赋成不同的值,要实现这个必须用到 List 类型。看下面一个基本例子(GroovyConsole)

基本语法就是

右边中括号声明的是一个 ArrayList, 右边对等位置找到相应的值逐个赋给左边的变量, 前面的例子实际可以理解为下面的过程

凡事都得举一反三

  1. 前面赋值是左右元素数目相等,如果是左短右长,或左长右短会是怎样
  2. 如果只需提取右端列表的某几个元素一条语句该如何做
  3. 函数如何返回多个值,以及如何一条语句接受函数返回的多个值
  4. 是否能一条语句获得自定义对象(非 List) 的多个属性值
  5. 正则表达式多组捕获的字符串是否能一次性的赋给多个变量

一般情况下我比较爱在 Groovy Shell  下进行简单的测试,但是发现 Groovy Shell  下用 def (a, b) = [1, 2] 的形式有个 Bug,去掉 def  关键字就可以了, 看下面的截图

加了 def 关键字后 id 和 name 两个变量反而不可见了,所以接下来的测试中我仍然用 Groovy Shell, 但是会把  def 关键字隐去。

左边变量数目多于右边列表元素

左边多余的变量会被声明为 null 值

左边变量数目少于右边列表元素

列表从左自右只提取需要的元素分别赋值左边的变量

关于任意位置提取右边 List 的元素

Groovy 无法简单像 Scala 那样提取任意位置的元素,而必须显式的用  [index] 或 getAt(index) 方法。例如

上面直接用的 list[0], list[1], 和  list[2..01] 来得到 a, b, rest 的值。

而 Scala 从 Tuple 或各类集合中提取元素所展现的是它强大的模式匹配功能,Groovy 在这点上是不太具备的。

Groovy 方法同时返回多个值

有了以上的知识后,要实现 Groovy 方法返回多值就好办了,只要让方法返回一个 List 就行,接收端用 (a, b) = foo() 来进行多重赋值

从自定定义对象一次性提取多个属性值

比如,对于一个自定义对象 User,获得实例 user 后,需要分别用 user.id  和 user.name 来得到 id 和 name

那是否能用下面的形式一次性声明 id 和 name 两个变量,并从 user 实例中获得相应的值呢?

Groovy 报出异常

Exception thrown
groovy.lang.MissingMethodException: No signature of method: User.getAt() is applicable for argument types: (java.lang.Integer) values: [0]
Possible solutions: getAt(java.lang.String), getId(), setId(java.lang.Integer), getName(), putAt(java.lang.String, java.lang.Object), wait()

这个线索给予我们的是 User 类需要实现 getAt(Integer) 方法,因此对代码的改造如下

def (id, name) = new User(1, 'Yanbin') 相当于执行了

正则表达式中同时捕获多组值赋给多个变量

代码演示

exp, amount 和  currency 的值分别为 12 Euro, 12 和 Euro。同样的,正则表达式分组中第一个元素是被匹配的字符串本身。

链接:

  1. Groovy Goodness: Multiple Assignments
  2. Getting tail of a list in Multiple Assignment in Groovy
  3. Groovy中的隐式构造函数

本文链接 https://yanbin.blog/groovy-multiple-assignment-returns/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

7 Comments
Inline Feedbacks
View all comments
wayne
wayne
6 years ago

没有关注过groovy,它能解决什么问题的?

Yanbin
6 years ago
Reply to  wayne

特定领域里用它,像 Jenkins, SoupUI(ReadyAPI), 就是写 Java 觉得有些罗嗦就换成 Groovy 来写。Groovy 并不是用来解决 Java 不容易解决的问题,而 Scala 比 Java 相对来说要高级些。看它们的生态,Groovy 有 Grails, Gradle,不足轻重,而 Scala 有 Spark, Kafka, PlayFramework, Akka,在业界的影响力就不可同日而语。

wayne
wayne
5 years ago
Reply to  Yanbin

噢,这样的,受教。
我的理解中scala是属于函数式编程,java先jdk8开始也支持这样了,不太理解的是高级的地方是指什么方面?并没有了解scala,望见谅,可能问的有点低级。

wayne
wayne
5 years ago
Reply to  Yanbin

scala相较于java,是不是也像您上面说的那样,不同的体系。scala之于spack,kafka,而java之于spring,mybatis等等,是这样的意思吗?
好奇的一点是,高效框架,是指框架本身的性能比较高?还是使用scala开发的框架比较高效?还是使用scala开发程序比较高效呢?

wayne
wayne
5 years ago
Reply to  Yanbin

噢~,受教,明白了