2Groovy闭包与方法引用
Groovy闭包与方法引用本文主要介绍闭包,方法引用相关知识。 this、owner和delegate每个闭包都有这3个概念,this、owner和delegate,这3个概念很像,容易搞糊涂。
this一个闭包的this指向的必然是一个class对象,而不是闭包对象,如下所示,
class Enclosing {
void run() {
def whatIsThisObject = { getThisObject() }
assert whatIsThisObject() == this
def whatIsThis = { this }
assert whatIsThis() == this
}
}
class EnclosedInInnerClass {
class Inner {
Closure cl = { this }
}
void run() {
def inner = new Inner()
assert inner.cl() == inner
}
}
class NestedClosures {
void run() {
def nestedClosures = {
def cl = { this }
cl()
}
assert nestedClosures() == this
}
}
ownerowner跟this基本一样,唯一不同就是owner可以是闭包。所以下边代码里的cl的owner就是nestedClosures。 class NestedClosures {
void run() {
def nestedClosures = {
def cl = { owner }
cl()
}
assert nestedClosures() == nestedClosures
}
}
delegatedelegate是groovy里比较难理解的概念,简单的说如果一个闭包在执行的时候发现某个参数未定义,那么就会去他的owner以及delegate里面找(默认是先owner后delegate)。其实这么说起来delegate就是相当于java里的非静态内部类持有外部类的引用,delegate就是外部类的引用。默认情况下delegate就是owner。delegate在DSL里面是非常有用的。 例子1如下所示,say这个闭包需要m变量,但是m未定义,如果直接执行say()肯定不行,在这里我们给say.delegate=eee,而eee这个map里边是有m这个变量的,所以在L9执行的时候,发现闭包内m未定义,就去他的delegate eee里找,找到了m,所以最后结果就是打印出2 def say = {
println m
}
//say.delegate = [m:2]
eee=[m:2]
assert eee.m==2
say.delegate=eee
say()
例子2class Person {
String name
}
class Thing {
String name
}
def p = new Person(name: 'Norman')
def t = new Thing(name: 'Teapot')
//闭包
def upperCasedName = { delegate.name.toUpperCase() }
upperCasedName.delegate = p
assert upperCasedName() == 'NORMAN'
upperCasedName.delegate = t
assert upperCasedName() == 'TEAPOT'
在这里,我们定义了一个闭包upperCasedName,通过指定delegate,改变闭包的执行主体,这看起来和传函数参数类似。闭包的delegate是可以不写的,因为闭包找不到成员的时候就会调用delegate的方法,所以闭包可以这么写 def upperCasedName = { name.toUpperCase() }
字符串插值我们知道在字符串插值的时候,可以用 def number = 1
def eagerGString = "value == ${number}"
def lazyGString = "value == ${ -> number }"
assert eagerGString == "value == 1"
assert lazyGString == "value == 1"
number = 2
assert eagerGString == "value == 1"
assert lazyGString == "value == 2"
其他如果一个函数与一个闭包拥有相同的名称和参数,则调用的时候将执行函数,而不是闭包 方法引用操作符
|