Gradle Cheat Sheet (2): Groovy Closures and Objects
Groovy可以通过Closure(闭包)来定义函数,闭包有两个特点:闭包可以像数值和字符串类型那样被赋给变量,也可以访问其作用域外的变量。
Contents
1. 闭包的声明和调用
使用def 声明闭包,注意这里和声明函数相比多了等号= :
def foo = "One million dollars" def myClosure = { println "Hello from a closure" println "The value of foo is $foo" }
闭包的调用和函数类似:
myClosure()
输出为:
Hello from a closure The value of foo is One million dollars
注意foo的定义在myClosure的作用域之外,myClosure可以获取其作用域之外的变量。
一个闭包实际上是groovy.lang.Closure的实例,可以把闭包赋给变量:
def bar = myClosure def baz = bar baz()
输出为:
Hello from a closure The value of foo is One million dollars
2. 闭包的参数
使用-> 分隔参数列表和闭包体,形式上类似于Lambda表达式。
def doubleIt = { x -> x + x}
3. 高阶函数
Groovy支持高阶函数(Higher order function),可以把函数作为参数传递给函数。如:
def applyTwice(func, arg){ func(func(arg)) } foo = 5 def fooDoubledTwice = applyTwice(doubleIt, foo) println "Applying doubleIt twice to $foo equals $fooDoubledTwice"
输出为:
Applying doubleIt twice to 5 equals 20
applyTwice 的第一个参数func 是一个函数,在arg 上应用两次func 。
这里函数作为“一等公民”,像数值和字符串类型一样进行传递,可以实现函数式编程的范式。如:
def myList = ["Gradle", "Groovy", "Android"] def printItem = {item -> println "List item: $item"} myList.each(printItem)
输出为:
List item: Gradle List item: Groovy List item: Android
即在列表myList 的每一个元素上执行闭包printItem 。
可以在行内定义闭包,如果闭包只接受一个参数,则可以直接用it指代:
myList.each{println "Compactly printing each list item: $it"}
输出为:
Compactly printing each list item: Gradle Compactly printing each list item: Groovy Compactly printing each list item: Android
4. 委托
闭包可以拥有委托对象,如果闭包中用到的变量和方法在闭包本地没有定义,则会继续在闭包的委托对象中寻找。
首先定义一个GroovyGreeter类:
class GroovyGreeter { String greeting = "Default greeting" def printGreeting(){println "Greeting: $greeting"} } def myGroovyGreeter = new GroovyGreeter() myGroovyGreeter.printGreeting() myGroovyGreeter.greeting = "My custom greeting" myGroovyGreeter.printGreeting()
输出为:
Greeting: Default greeting Greeting: My custom greeting
这里对GroovyGreeter 类的定义使用了简化的方法,但其本质还是一个Java类。Groovy会自动为类的成员变量(如greeting)添加getter和setter。
然后定义greetingClosure 如下:
def greetingClosure = { greeting = "Setting the greeting from a closure" printGreeting() }
注意greetingClosure 中没有定义printGreeting() ,直接运行greetingClosure() 会报错。这里希望greetingClosure 中的printGreeting() 使用GroovyGreeter 中的同名函数,就需要先通过greetingClosure.delegate 把之前实例化的myGroovyGreeter 设置为greetingClosure 的委托对象:
greetingClosure.delegate = myGroovyGreeter greetingClosure()
输出为:
Greeting: Setting the greeting from a closure
本部分的完整代码可以在这里找到。