首先看一段Java代码: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机制,看下面的例子:app
// 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 。ide
同时咱们还应该注意另一点,首先看下面这个例子:测试
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() } }
输出结果:this
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) 。spa
Groovy "with"的问题: code
首先看一段测试代码:get
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()
打印结果为:it
wrong add: before Foo$_doit_closure1@1979eb [1, 2, 3, "after"]
从闭包的解析策略,咱们看到,默认的策略为OWNER_FIRST,这样的话,至关于咱们with中的全部调用都会委托给owner,这样的问题是,若是咱们未来在闭包外增长了一个同名的方法,那么with中的调用将不会按照预期进行,好的解决方法是在with中手动指定策略为DELEGATE_ONLY。
从上面的分析咱们不难看懂最后的这个例子,由于each操做是Objec的方法,他其实调用的是Object的方法,这样咱们的with中就不能调用全部Object的方法!