Groovy 闭包进阶

1. 闭包关键变量

闭包自带this,owner和delegate关键字。下面写一段测试代码,分别输出闭包这3个变量的值:

def testClouser = {
    println "testClouser this:" + this
    println "testClouser owner:" + owner
    println "testClouser delegate:" + delegate
}

testClouser.call()

输出结果:

testClouser this:variable.variablestudy@662b4c69
testClouser owner:variable.variablestudy@662b4c69
testClouser delegate:variable.variablestudy@662b4c69

可以看到这3个变量输出的值是一样的。
this:表示闭包定义处的类
owner:表示闭包定义处的类或者对象
delegate:表示任意对象,有一个默认值和owner一致
下面多定义几个闭包,测试不同场景下3个参数所代表的的对象。

class Person {
    def static classClouser = {
        println "testClouser this:" + this
        println "testClouser owner:" + owner
        println "testClouser delegate:" + delegate
    }

    def static say() {
        def classClouser = {
            println "methodTestClouser this:" + this
            println "methodTestClouser owner:" + owner
            println "methodTestClouser delegate:" + delegate
        }
        classClouser.call()
    }
}
Person.classClouser.call()
Person.say()

输出结果:

testClouser this:class variable.Person
testClouser owner:class variable.Person
testClouser delegate:class variable.Person
methodTestClouser this:class variable.Person
methodTestClouser owner:class variable.Person
methodTestClouser delegate:class variable.Person

输出结果指向的是类的字节码,不是具体的对象,是因为我们定义的都是static的闭包。
把代码中的static去掉:

class Person {
    def classClouser = {
        println "testClouser this:" + this
        println "testClouser owner:" + owner
        println "testClouser delegate:" + delegate
    }

    def say() {
        def classClouser = {
            println "methodTestClouser this:" + this
            println "methodTestClouser owner:" + owner
            println "methodTestClouser delegate:" + delegate
        }
        classClouser.call()
    }
}
Person p = new Person()
p.classClouser.call()
p.say()

输出结果:

testClouser this:variable.Person@28f2a10f
testClouser owner:variable.Person@28f2a10f
testClouser delegate:variable.Person@28f2a10f
methodTestClouser this:variable.Person@28f2a10f
methodTestClouser owner:variable.Person@28f2a10f
methodTestClouser delegate:variable.Person@28f2a10f

这时候的输出就指向了Person具体对象。
这表明闭包对象this,owner,delegate默认指向最近的封闭类。
下面在闭包中定义闭包,看看这3个变量的值是否一样。

def nestClouser = {
    def innerClouser = {
        println "innerClouser this:" + this
        println "innerClouser owner:" + owner
        println "innerClouser delegate:" + delegate
    }
    innerClouser.call()
}
nestClouser.call()

输出结果:

innerClouser this:variable.variablestudy@28f2a10f
innerClouser owner:variable.variablestudy$_run_closure2@7205765b
innerClouser delegate:variable.variablestudy$_run_closure2@7205765b

可以看到,this指向了闭包定义处的类,owner和delegate一样,都指向了闭包。
如果在类或方法中定义闭包,this,owner,delegate3个变量的值是一样的。如果在闭包里面嵌套定义了闭包,this与owner和delegate的值就不一样了。this还会指向闭包定义处的类的实例或类本身。owner和delegate会指向最近的闭包对象。
那什么情况下owner和delegate会不同了,在代码中手动修改delegate的值:

class Person {

}
Person p = new Person()

def nestClouser = {
    def innerClouser = {
        println "innerClouser this:" + this
        println "innerClouser owner:" + owner
        println "innerClouser delegate:" + delegate
    }
    innerClouser.delegate = p
    innerClouser.call()
}
nestClouser.call()

输出结果:

innerClouser this:variable.variablestudy@7133da86
innerClouser owner:variable.variablestudy$_run_closure2@20ccf40b
innerClouser delegate:variable.Person@2fb3536e

当认为修改delegate的值时,owner和delegate就会出现不一样的情况。
总结:
在大多数场景下,this,owner和delegate的值都是一样的。
在闭包中定义闭包时,this与owner和delegate的值不一样。
在修改闭包的delegate参数时,owner和delegate的值不一样。
this和owner是不可以修改的,delegate可以做做任意修改。

2. 闭包委托策略

先看一段简单的代码:

class Student {
    String name
    def pretty = {"My name is ${name}"}
    String toString() {
        pretty.call()
    }
}

class Teacher {
    String name
}

def stu = new Student(name : 'Sarash')
def tea = new Teacher(name : 'Teacher')
println stu.toString()

输出结果:

My name is Sarash

把上面代码的pretty闭包的delegate和resolveStrategy修改一下:

class Student {
    String name
    def pretty = {"My name is ${name}"}
    String toString() {
        pretty.call()
    }
}

class Teacher {
    String name
}

def stu = new Student(name : 'Sarash')
def tea = new Teacher(name : 'Teacher')
stu.pretty.delegate = tea
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println stu.toString()

输出结果:

My name is Teacher

从结果可以看出闭包优先从tea查找变量,找到之后进行输出。
如果把Teacher的name改成其他命名,由于我们设置了Closure.DELEGATE_FIRST,它先从委托对象寻找,然后从owner对象寻找,最后在Student找到了name属性,进行输出。如果改成Closure.DELEGATE_ONLY,name在Teacher对象找不到name属性,代码会报错。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值