指南 2 - 基于数据、闭包编码

闭包(closure)

使Groovy与大多数编译语言不同的其中一件事情是,你可以创建函数作为第一类对象。也就是说,你可以定义一段代码,然后就像一个字符串或者一个整数一样的传递它。请看下面的代码:

square = { it * it }

表达式“it * it”周围的大括号告诉Groovy编译器把这个表达式当作代码处理。在软件的世界里,这称为“闭包”。在这个例子中,标志符“it”表示任何传给这个函数的值。然后这个已编译的函数被赋值给变量“square”,就像上面一样。所以现在我们可以像下面一样做些事情:

square(9)

并且得到值81。

这没有很有趣,直到我们发现可以把这个函数“square”当作一个值来传递。有一些内置的函数把像这样的函数作为一个参数。其中一个例子就是数组的“collect”方法。请试试下面的代码:

[ 1, 2, 3, 4 ].collect(square)

这个表达式的意思是,用值1、2、3、4创建一个数组,然后调用“collect”方法,并传入我们之前定义的闭包。collect方法遍历数组中的每个元素,并用这些元素调用闭包,然后把结果放入一个新的数组中,最后的结果是:

[ 1, 4, 9, 16 ]

更多以闭包作为参数的方法,请查看Groovy GDK文档

闭包默认只有一个参数,这个参数被称为“it”,你也可以以命名的参数创建闭包。例如,方法Map.each()可以传入包含两个参数的闭包,这两个参数分别绑定了键(key)和对应的值:

printMapClosure = { key, value -> println key + "=" + value }
[ "yue" : "wu", "lane" : "burks", "sudha" : "saseethiaseeleethialeselan" ].each(printMapClosure)

输出结果:

yue=wu
lane=burks
sudha=saseethiaseeleethialeselan

更多闭包的例子

下面是更多的一些闭包的例子。第一个例子说明了两件事情。第一,这个闭包与在它外面的变量进行了交互。也就是说,这个闭包的目的是,通过把保存在数组orderParts中的存货订单的各部分,添加(追加)到变量fullString中,来把它们放到一起。变量fullString并不在这个闭包中。第二,这个闭包是“匿名的”,意思是它没有名字,并且在each方法被调用的时候被定义。

fullString = ""
orderParts = ["BUY", 200, "Hot Dogs", "1"]
orderParts.each {
  fullString += it + " "
}
 
println fullString

你大概可以猜到输出是什么了。

下一个例子是另外一个匿名闭包,这次是计算保存在一个映射(map)中的值的总和。

myMap = ["asdf": 1 , "qwer" : 2, "sdfg" : 10]
 
result = 0
myMap.keySet().each( { result+= myMap[it] } )
println result

处理文件

从文件中读取数据是相对简单的。首先创建一个文本文件,并且命名为myfile.txt。文件内容是什么没有关系,只要随便输入些文字,然后保存在你的C:盘的\temp目录下就可以了。然后在groovyConsole中输入以下代码:

myFileDirectory = "C:\\temp\\"
myFileName = "myfile.txt"
myFile = new File(myFileDirectory + myFileName)
 
printFileLine = { println "File line: " + it }
 
myFile.eachLine( printFileLine )

这会输出文件中的每一行内容,并且在每行前面加上“File line: ”。代码的前两行只是简单的声明了两个变量来指定文件的位置。变量名没有任何特别的意义,就如你所见的,我们所做的只是在使用它们的时候把它们连接在一起。注意,因为反斜杠在Groovy中有特殊的含义,所以你必须使用两个反斜杠来告诉它你“确实”打算表示一个反斜杠。

接下来的以“myFile =”开头的一行创建了一个新的File对象。一个对象只是一些相关的方法和数据的集合。例如,一个文件对象可能包含描述它的位置的数据(在这个例子中是“C:\temp\myfile.txt”),也可能包含一个当文件存在时则删除它的方法。在这个例子中,我们使用的唯一方法是eachLine方法,我们在代码的最后一样调用了这个方法。这行的上面一行是一个简单的闭包定义,关于这点你应该已经看过很多次了。

处理字符串

Groovy中的字符串拥有Java字符串的全部功能。也就是说,一个Groovy字符串只是一个添加了一些额外的东西的Java字符串。正因如此,我们可以查阅Java文档中关于String类的部分,来找出一些我们可以用它来完成的有趣的事情。例如,请查看标题为“方法概要”的一节中关于“split”方法的描述。这个方法完成了一些非常有用的事情,它根据一个正则表达式来分割一个字符串。稍后我们将讨论更多关于正则表达式的事情,但是现在你唯一需要知道的事情就是,最简单的正则表达式就是一个单独的字符。所以,譬如我们想把日期“2005-07-04”分割为不同的组成部分,以便我们可以在年上加一,从而得到下一年的7月4号。我们可以:

stringDate = "2005-07-04"
dateArray = stringDate.split("-")	// split()使用正则表达式,所以你需要使用转义字符,譬如“.” -> “\\.”
year = dateArray[0].toInteger()
year = year + 1
newDate = year + "-" + dateArray[1] + "-" + dateArray[2]

这段代码把我们之前讨论过的很多事情都结合在一起了。有两件新的事情,第一件是字符串的split方法的使用。第二件是字符串的toInteger()的调用。toInteger的调用只是告诉Groovy你想把数据当作数字处理,而不是字符串。如果你删掉第三行末尾的“.toInteger()”之后运行这段代码,看看会发生什么。

另外一件你可能会注意到的事情是,在Java字符串的文档中并没有列出toInteger方法。这是因为它是Groovy给字符串添加的额外的特征之一。你也可以看一下Groovy对Java对象的扩展的文档。

 
wiki/getting_started_guide/tutorial_2.txt · 最后更改: 2008-07-08 00:14 由 johnny
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki