Groovy "with"

首先看一段Java代码:

// PrintIndependenceDay.java

import java.util.Calendar;
import java.util.Date;

public class PrintIndependenceDay {

  public static void main(String[] args) {
    Calendar calendar = Calendar.getInstance();
    calendar.clear();
    calendar.set(Calendar.MONTH, Calendar.JULY);
    calendar.set(Calendar.DATE, 4);
    calendar.set(Calendar.YEAR, 1776);
    Date time = calendar.getTime();
    System.out.println(time);
  }
}

这段代码中我们获得Calendar的实例,然后反复的调用它的方法。是否觉得冗余,因为我们的上下文环境是已知的,在Groovy中我们利用“with”来简化,上面的代码等价的Groovy代码如下:

// PrintIndependenceDay.groovy

def calendar = Calendar.instance
calendar.with {
  clear()
  set MONTH, JULY
  set DATE, 4
  set YEAR, 1776
  println time
}

是不是很简洁,我们还有更炫的功能,这要得益于delegate机制,看下面的例子:

// define a closure
def myClosure = {
  // call a method that does not exist
  append 'Jeff'
  append ' was here.'
}

// assign a delegate to the closure
def sb = new StringBuffer()
myClosure.delegate = sb

// execute the closure
myClosure()

assert 'Jeff was here.' == sb.toString()

通过动态机制,我们把闭包操作委托给了StringBuffer,我们要注意的是传递给闭包的只是StringBuffer的一个clone

同时我们还应该注意另外一点,首先看下面这个例子:

class ResolutionTest {  
      
    def append(arg) {  
        println "you called the append method and passed ${arg}"  
    }  
      
    def doIt() {  
        def myclosure = {  
            append 'Jeff was here.' 
        }  
          
        def buffer = new StringBuffer()  
          
        myclosure.delegate = buffer  
          
        // the append method in this ResolutionTest  
        // will be called because resolveStrategy is  
        // OWNER_FIRST (the default)  
        myclosure()

        println '---------------------------------'  

        // give the delegate first crack at method  
        // calls made inside the closure  
        myclosure.resolveStrategy = Closure.DELEGATE_FIRST  
          
        // the append method on buffer will  
        // be called because the delegate gets  
        // first crack at the call to append()  
        println myclosure()  
    }  
      
    static void main(String[] a) {  
        new ResolutionTest().doIt()  
    }  
}

输出结果:

you called the append method and passed Jeff was here.
---------------------------------
Jeff was here.

这里我们要注意闭包一个高级特性:闭包内部有一个策略来决定何时把调用发送给委托者,每一个Groovy的闭包有一个与之关联的属性:resolveStrategy。它有四个常量取值:OWNER_FIRST, DELEGATE_FIRST, OWNER_ONLY and DELEGATE_ONLY(都定义在groovy.lang.Closure中,默认取值为:OWNER_FIRST)

 

Groovy "with"的问题:

 

首先看一段测试代码:

class Foo {
    def add(x) {
        println "wrong add: $x"
    }
    def doit(x) {
        def n = [1,2,3]       
        n.with {
          add(x)
          each { println it }
        }

        n.add("after")     
        println n
    }
    def test() {
        doit("before")        
    }
}
new Foo().test()

打印结果为:

wrong add: before
Foo$_doit_closure1@1979eb
[1, 2, 3, "after"]

      从闭包的解析策略,我们看到,默认的策略为OWNER_FIRST,这样的话,相当于我们with中的所有调用都会委托给owner,这样的问题是,如果我们将来在闭包外增加了一个同名的方法,那么with中的调用将不会按照预期进行,好的解决方法是在with中手动指定策略为DELEGATE_ONLY。

      从上面的分析我们不难看懂最后的这个例子,因为each操作是Objec的方法,他其实调用的是Object的方法,这样我们的with中就不能调用所有Object的方法!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值