groovy之closure
来源:互联网 发布:阿里妈妈淘宝客优惠券 编辑:程序博客网 时间:2024/05/14 20:52
什么是闭包(Closure)
在Groovy中,闭包是一段匿名的代码段,它可以有参数,返回值,并且能够赋值给一个变量。闭包中使用的变量可以是在闭包外部定义的,也可以是在闭包内部定义的。
闭包定义的语法如下
- 1
- 2
上面的方括号[]表示闭包的参数可有可无,所以正常的闭包可能包括如下这些类型:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
闭包是一个对象
闭包是groovy.lang.Closure的一个实例,所以它可以跟Java中的基础类型int,string,boolean一样,可以用来定义变量,函数参数等。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
注意上面的函数调用,它可以不带括号,也可以带括号。并且实参可以是一个外部已定义的闭包,也可以是一个匿名闭包(最后的一个闭包就是匿名闭包,看到这里,用过gradle编译android的朋友们是否感觉很熟悉,这里只是提示一下,后面会重点说明)
还有一个挺有意思的情况就是,如果一个函数的最后一个参数是闭包,那么可以写成如下形式:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
最有意思的是最后一个函数调用,第一个参数是使用括号的,如果最后一个参数是Closure,那么还可以写成如上代码这样的形式。
如何调用闭包
- 1
- 2
- 3
- 4
闭包有两种调用方式,一种是直接使用(),另外一种使用.call()来调用。另外从上面代码段可以看出,闭包的返回值为最后一行代码的计算结果。
闭包的参数
闭包参数分为三种,一种是普通参数,一种是隐式参数,另一种是可变长度参数。
普通参数可以有一个可选的类型,一个参数名,还有一个可选的默认值
def closure = {int intValue = 0 ->
println intValue
}
closure() //结果:0
def closure = {intValue = 0 ->
println intValue
}
closure() //结果:0
def closure = {intValue ->
println intValue
}
closure(0) //结果:0
如果没有明确使用->来定义参数列表,那么这个闭包就定义了一个隐式的参数,这个隐式参数名叫it。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
最后一个闭包调用会出错,因为参数列表定义为空,所以这个时候没有默认参数it。
在闭包中也可以使用可变长度参数,示例如下
- 1
- 2
- 3
- 4
- 5
委托策略
对于闭包来说,委托是一个重要的概念,你可以随时改变委托或者委托策略。
如果想要理解委托,那么我们先要解释一下委托中使用的三个重要的变量:
- this 代表的是闭包定义所在的类的对象
- owner 代表的是闭包定义所在的类或者闭包对象
- delegate 代表的是第三方对象,在这个第三方对象中你可以找到闭包中未定义的方法调用或者属性
如果没有理解上面的三个概念,那没有关系,下面看看列子就知道是什么意思了。
this的使用例子
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
从这个例子中,我们可以看出this跟Java语言中概念一致,就是当前类变量,不管是在闭包里访问,还是在闭包的闭包里访问,都是一致的。
闭包的owner属性
闭包的owner就是直接包括闭包的类或者闭包对象, 也就是说如果闭包直接定义在类中,那么owner就是类对象,如果闭包直接定义在闭包中,那么owner就是闭包对象,看看例子就明白了。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
闭包的delegate属性
闭包的默认delegate属性是owner,不过你可以更改delegate属性,也可以更改delegate策略。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
delegate的使用
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
从这里看出,定义闭包的时候,name属性还没有定义,闭包是通过delegate的对象来获取该对象的name属性的。
delegate的策略
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
请看下面这个例子
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
闭包的委托策略类型有如下几种:
- Closure.OWNER_FIRST 这个是闭包的默认委托策略,如果这个属性/方法在owner中存在,那么就使用owner中的属性/方法。否则,使用delegate的属性/方法
- Closure.DELEGATE_FIRST 解析逻辑,如果delegate中有这个属性/方法,那么使用delegate中的属性/方法。否则,使用owner中的
- Closure.OWNER_ONLY 解析逻辑,只在owner中查看这个属性/方法,delegate中的忽略
- Closure.DELEGATE_ONLY 解析逻辑,只在delegate中查看这个属性/方法,owner中的忽略
Closure.TO_SELF 自定义,比较复杂,不怎么使用
class Person{
String name
def closure = {“nameis {age} years old”}
}class Thing{
String name
int age
}def person = new Person(name:’Mary’)
def thing = new Thing(name:’Cat’, age:2)
person.closure.delegate = thing
person.closure.resolveStrategy = Closure.OWNER_ONLY
person.closure() //结果: Caught: groovy.lang.MissingPropertyException: No such property:
age for class: Person
上面的例子虽然将thing对象委托给闭包,但是因为委托策略为OWNER_ONLY,所以,即使delegate对象中存在age属性,但是这个闭包还是不能访问。
有了这些Groovy语言基础,再去看gradle脚本,应该会感觉容易些。而且如果碰到不清楚的地方,直接去查看DSL文档就行,毕竟gradle脚本实际上就是一些API的调用。在下面的一篇文章中会简单介绍如何去查看DSL的API,以及gradle工具是如何去解析定义在build.gradle文件的。
- Groovy 之 Closure
- groovy之closure
- Groovy Closure简介
- New Groovy --- Closure/Block问题
- Groovy中closure的delegate
- Groovy解惑——closure中的delegate
- Groovy解惑——closure中的owner
- Groovy中Closure的this到底指向谁?
- Groovy基础——Closure(闭包)详解
- Groovy基础——Closure(闭包)详解
- Groovy基础——Closure(闭包)详解
- Groovy基础——Closure(闭包)详解
- Groovy基础——Closure(闭包)详解
- javascript 之 Closure
- javascript必知必会之closure
- javascript必知必会之closure
- PHP7之Closure::call()
- 闭包之Closure
- Linux相关指令
- 11.28学习计划
- linux终端运行.sh文件
- MAC Safari Xcode VSCode Iterm常用快捷键
- TensorFlow学习笔记8:CNN搭建(layer,estimator等)
- groovy之closure
- dedecms织梦后台模板layui框架-20171126更新
- HDU 1274 展开字符串(递归)
- c语言函数
- 自己整理的知识点 “算法排序和查找”
- [python]使用channels库时遇到的一些问题
- 链式栈实现迷宫寻径
- Hibernate 级联删除异常 deleted object would be re-saved by cascade
- CSS3-转换之scale