theme: condensed-night-purple
作用
属性
闭包中有三个属性,this,owner,delegete。可在闭包中直接获取。
this:代表定义当前闭包的类。
如果是内部类,就是只想内部类名。
owner:代表定义当前闭包的类或者闭包。
如果当前闭包是在闭包中定义的,那么owner的值就是当前闭包(比如closure2是在closure1中定义的,那么closure2的owner就是closure2);除了上面那种情况剩下的就和this一样了
delegete:默认是和owner一致。除非自定义delegete
自定义delegete
上面三个熟悉中功能最强的用的最多的也就是delegete了,比如利用android方法传入的闭包设置必要的属性
顾名思义属性委托,那么委托给谁?把什么委托?
一句话:把属性委托给闭包
下面来看一段代码:
可用在线代码平台直接运行: https://tool.lu/coderunner/
代码语言:javascript复制class Main {
//闭包内部
def cc = {
//重新定义Person的name属性
name ="Not is BeiYang"
//age并没有修改因此还是委托属性的值
println "delegete Person is $name age = $age"
//可调用属性的方法
eat("油条")
}
}
class Person {
String name
int age
int sex
void eat(String food) {
println("获得通过闭包给的食物: $food")
}
@Override
String toString() {
return "Person{"
"name='" name '''
", age=" age '''
", sex=" sex
'}'
}
}
Main main = new Main()
//创建类(也就是属性)
Person person = new Person(name : "BeiYang",age: 11,sex: 1)
//将person属性绑定到闭包上,即可在闭包内部使用委托属性的字段和方法了。
main.cc.delegate = person
//调用闭包
main.cc()
println person.toString()
代码结果: //name字段修改,age字段获取属性 delegete Person is Not is BeiYang age = 11 获得通过闭包给的食物: 油条 Person{name='Not is BeiYang', age=11', sex=1}
作用
可将属性和闭包绑定,这样闭包中就可以直接使用委托属性的字段和方法了;还有一种作用,闭包中设置的值也会同样设置给委托属性,因此在闭包中可以修改赋值。
第二种作用就是我们常见的通过android闭包设置属性
代码语言:javascript复制android {
//设置属性值
compileSdkVersion 25
buildToolsVersion "25.0.2"
//调用属性方法,参数依然是闭包,方法内部依然使用委托设置属性
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
}
冲突
问题: 闭包内如果有和属性相同的字段或者相同的方法的时候,这时候是怎么处理的?
相同属性
因为是将属性委托给了闭包,因此拥有相同字段的时候就相当于对这个字段重新赋值
相同方法
默认是使用delegete的,但是也可以通过设置delegete的策略来指定具体使用ower还是delegete。
修改:
代码语言:javascript复制这里只看特殊情况,当返回值不一致的时候也是会使用owner的方法;这里得提到方法签名,Groovy和Java都是基于JVM,但是对方法签名这块看完这个修改后会发现两个语言的方法签名不一样,可以去《深入理解JAVA虚拟机中》查找关于方法签名的知识。
class Main {
//闭包内部
def cc = {
//重新定义Person的name属性
name ="Not is BeiYang"
//age并没有修改因此还是委托属性的值
println "delegete Person is $name age = $age"
//可调用属性的方法
println eat("油条")
}
//返回值不一样
Integer eat(String food){
println "111"
return 111
}
}
class Person {
String name
int age
int sex
String eat(String food) {
println("获得通过闭包给的食物: $food")
return food
}
@Override
String toString() {
return "Person{"
"name='" name '''
", age=" age '''
", sex=" sex
'}'
}
}
在上面的代码的基础上做扩展得到的结论。一个注意点是Groovy中没有基本类型都是包装类型,需要返回Integer 。
打印:
代码语言:javascript复制delegete Person is Not is BeiYang age = 11
111
111
Person{name='Not is BeiYang', age=11', sex=1}
委托策略
- Closure.OWNER_FIRST是默认策略。优先在owner寻找,owner没有再delegate
- Closure.DELEGATE_FIRST:优先在delegate寻找,delegate没有再owner
- Closure.OWNER_ONLY:只在owner中寻找
- Closure.DELEGATE_ONLY:只在delegate中寻找
- Closure.TO_SELF:暂时没有用到,哎不知道啥意思
使用方法是在调用delegete之前调用闭包的方法:main.cc.setResolveStrategy(Closure.OWNER_FIRST)
效果读者自行尝试吧~~~