zoukankan      html  css  js  c++  java
  • groovy 闭包

    语法规则

    { [closureParameters -> ] statements }

    下面的语句都是正确的

     1 { item++ }
     2 { -> item++ }
     3 { println it }
     4 { it -> println it }
     5 { name -> println name }
     6 { String x, int y -> println "hey ${x} the value is ${y}" }
     7 { reader ->
     8     def line = reader.readLine()
     9     line.trim()
    10 }

    参数列表

    1 def closureWithTwoArgsAndOptionalTypes = { a, int b -> a+b }
    2 assert closureWithTwoArgsAndOptionalTypes(1,2) == 3

    可以看到参数列表使用逗号分隔,而且 typed 和 untyped 均可,-> 符号用以分隔参数列表和语句。值得提一下,如果闭包只有一个参数,那么可以省略参数列表,直接使用 it 代替参数。

    委托策略

    闭包有三个概念:this、owner 和 delegate

    this 定义闭包的封闭类(enclosing class)

    owner 定义闭包的封闭对象(enclosing object),可能是类也可能是对象

    delegate 被调用方法或者引用属性的第三方对象,这个需要具体参考代码

    this

     1 class Enclosing {
     2     void run() {
     3         def whatIsThisObject = { getThisObject() }          // 返回对象 this
     4         assert whatIsThisObject() == this
     5         def whatIsThis = { this }                           // 返回对象 this
     6         assert whatIsThis() == this
     7     }
     8 }
     9 class EnclosedInInnerClass {
    10     class Inner {
    11         Closure cl = { this }                               // Inner 类的对象 this
    12     }
    13     void run() {
    14         def inner = new Inner()
    15         assert inner.cl() == inner
    16     }
    17 }
    18 class NestedClosures {
    19     void run() {
    20         def nestedClosures = {
    21             def cl = { this }                              
    22             cl()                                            // 还是 this
    23         }
    24         assert nestedClosures() == this
    25     }
    26 }

    可以看出 groovy 闭包中的 this 和 java 是一致的。

    owner

     1 class Enclosing {
     2     void run() {
     3         def whatIsOwnerMethod = { getOwner() }                  // 对象的 this
     4         assert whatIsOwnerMethod() == this
     5         def whatIsOwner = { owner }                             // 同样是对象的 this                   
     6         assert whatIsOwner() == this
     7     }
     8 }
     9 class EnclosedInInnerClass {
    10     class Inner {
    11         Closure cl = { owner }                                  // 本质上还是对象的 this
    12     }
    13     void run() {
    14         def inner = new Inner()
    15         assert inner.cl() == inner                           
    16     }
    17 }
    18 class NestedClosures {
    19     void run() {
    20         def nestedClosures = {
    21             def cl = { owner }                               
    22             cl()
    23         }
    24         assert nestedClosures() == nestedClosures            // 此处就是 this 就有区别了,和 owner 的语义一致
    25     }
    26 }

    delegate

    上面的 this 和 owner 引用的都是闭包 scope 的内容,但是 delegate 可以引用第三方对象的内容,默认 delegate 被设置为 owner,因为第三方对象不一定被设置。

     1 class Person {
     2     String name
     3 }
     4 class Thing {
     5     String name
     6 }
     7 
     8 def p = new Person(name: 'Norman')
     9 def t = new Thing(name: 'Teapot')
    10 
    11 def upperCasedName = { delegate.name.toUpperCase() } // delegate 可以省略 name.toUpperCase() 也是正确的
    12 
    13 upperCasedName.delegate = p
    14 assert upperCasedName() == 'NORMAN'
    15 upperCasedName.delegate = t
    16 assert upperCasedName() == 'TEAPOT'
    17 
    18 // 和引用外部变量有本质区别,下面的 target 不可能被省略
    19 def target = p
    20 def upperCasedNameUsingVar = { target.name.toUpperCase() }
    21 assert upperCasedNameUsingVar() == 'NORMAN'

    修改策略

    “默认 delegate 被设置为 owner”,这句话隐含意思就是 delegate 的策略可以被调整,有下面四种策略,

    Closure.OWNER_FIRST 默认的
    Closure.DELEGATE_FIRST delegate 优先
    Closure.OWNER_ONLY 只取 owner
    Closure.DELEGATE_ONLY 只取 delegate
    Closure.TO_SELF 如果用户自己实现 Closure 的子类,这个才有意义

     1 class Person {
     2     String name
     3     int age
     4     def fetchAge = { age }
     5 }
     6 class Thing {
     7     String name
     8 }
     9 
    10 def p = new Person(name:'Jessica', age:42)
    11 def t = new Thing(name:'Printer')
    12 def cl = p.fetchAge
    13 cl.delegate = p
    14 assert cl() == 42
    15 cl.delegate = t
    16 assert cl() == 42                   // 默认情况下 Closure.OWNER_FIRST,所以此处断言是通过的
    17 cl.resolveStrategy = Closure.DELEGATE_ONLY
    18 cl.delegate = p
    19 assert cl() == 42
    20 cl.delegate = t
    21 try {
    22     cl()                            // 只取 delegate,Thing 类无 age 字段,异常
    23     assert false
    24 } catch (MissingPropertyException ex) {
    25     // 异常会在这里被捕获
    26 }

    以上内容均参考 http://www.groovy-lang.org/closures.html,文档中还讲到了 closures in GStrings、currying 等很有意思的内容。

  • 相关阅读:
    Mysql数据库分库备份,分表备份
    KICKSTART无人值守安装
    git的使用
    iowait 过高问题的查找及解决linux
    Redis配置文件redis.conf详解
    安装和使用ZFS
    GlusterFS配置及使用
    Ceph与Gluster之开源存储的对比
    去掉Tomcat的管理页面
    Tomcat不加项目名称访问设置
  • 原文地址:https://www.cnblogs.com/wendellyi/p/5877157.html
Copyright © 2011-2022 走看看