Skip to end of metadata
Go to start of metadata

闭包(Closures)

Groovy 和大多数编译语言有很多区别,其中一点是你可以创建称为 first class object 的 function。也就是说你可以定义一段代码,它可以像 string 或 integer 那样传递。查看以下代码:

“it * it”外面的大括号告诉 Groovy 编译器把这个表达式当作代码处理。在软件领域,称之为“闭包”。在这里,指示符“it”指向传递到 function 中的值。然后编译后的 function 赋值到 “square”变量中。所以现在你可以这样做:

得到的值是 81。

可以像传值一样传递 funciton,这还不是很有趣。有一些内置的 function 像这样把 function 作为参数使用。其中一个是数组上的“collect”方法。试一下:

这个表达式的意思是,创建一个包含1、2、3、4的数组,然后调用“collect”方法,并使用上面定义的闭包作为参数。数组中的每个条目都会运行 collect 方法,它会在条目上调用闭包,然后把结果放入一个新的数组,结果是:

更多可以使用闭包作为参数的方法可以查看Groovy GDK 文档.

闭包默认地使用一个名为“it”的参数,你可以使用具名参数创建闭包。例如 Map.each() 方法可以使用有两个变量的闭包,两个变量绑定到 key 和相应的 value:

结果:

更多闭包示例

这里还有一些示例。第一个例子展示了多个事情。首先,闭包可以和外部的变量交互。也就是说,这个闭包的目的是将保存在 orderParts 数组中的股票订单的各部分通过追加到 fullString 变量从而组合到一起。 变量 fullString 并不在闭包中。其次,这个例子中使用的闭包是匿名的,意味着它没有名称,而且它定义在 each 方法的调用中。

或许你可以猜到输出是什么样。

下一个例子也是匿名闭包,这次汇总 map 中的值。

处理文件(Dealing with Files)

从文件中读取数据相对简单。先创建一个取名为 myfile.xtxt 的文本文件,随便在文件中输入一些内容,然后保存在 c:\temp 目录。然后在 groovyConsole 中输出以下代码:

就会在文件的每行前添加“File line:”前缀并输出。代码的前两行声名了两个变量表明文件所在位置。变量名没有什么特殊含义,就像你看到到,我们只是把它们组合到一起。注意反斜线在 Groovy 中有特殊含义,所以你必须使用两个反斜线来表示“实际的”反斜线。

以“myFile=”开始的一行创建了一个新的 File 对象。对象就是一个相关方法和数据的集合。例如,一个文件对象可能有描述它保存位置的描述,这里是“C:\temp\myfile.txt”,可能还有个方法用来删除它。这里我们唯一要使用的是 eachLine 方法,我们在最后一行中调用它。在这行之前是一个简单的闭包定义,这种定义在这篇文章中你已经看到很多次了。

处理字符串(Dealing with strings)

Groovy 中的字符串具有 Java 中字符串所有的功能。也就是说,Groovy 字符串对 Java 字符串做了一些扩展。所以我们可以参考 String 类的 Java 文档 找到一些可以对它做的有趣的事。例如,查看“split”方法描述中的标题为“方法概要(Methord Summary)”的章节。这个方法做了一些非常有用的事,就是使用正则表达式拆分字符串。后面我们会详细讨论正则表达式,这里你需要知道的是最简单的正则表达式是单独的一个字符。如果我们想把日期“2005-07-04”拆分成几部分,然后就可以在年上加1以获得下一个7月4日的日期。可以这样:

这段代码综合了我们前面已经说到的一些东西。还有两样新的,第一个是使用 String 的 split 方法,第二个是调用 String 的 toInteger() 方法。toInteger 方法的调用是告诉 Groovy 你想把数据作为整数,而不是字符串。可以试试在第3行末尾如果没有“.toInteger()”看会发生什么。

其它你可能需要注意的是在 Java 的 String 文档中没有 toInteger 方法,因为这是 Groovy 对 String 做的扩展中的一个。你还可以查看一下Groovy 对 Java 对象的扩展的文档。

  • No labels