6. 闭包(Closure)
闭包其实就是一段代码,但他们又是封装成一个Closure对象。可以类比为java的内部类,或者更好的是C++中的函数对象又叫仿函数(functor)。
闭包使得groovy的代码看起来更简洁,精炼。另外闭包可以使得资源处理更为简便。
例如:
new File(/testfile.txt/).eachLine {println it} // eachLine handle file close automatically
其中的it是闭包默认的变量名。
6.1 声明闭包
前面都是简单的在用的时候直接声明闭包,其实也可以将闭包复制给一个变量,便于多处使用,甚至引用一个已存在对象的方法。闭包也支持默认参数。
def linePrinter = {println it} // assign to a variable linePrinter('this line') // call class Foo { void bar(int value) { println "call int bar(int value), with params: $value" } void bar(List lst) { println "call int bar(List lst), with params: $lst" } void bar(int x, int y) { println "call int bar(int x, int y), with params: $x, $y" } } Foo foo = new Foo() foo.bar(10) // normal call Closure cls = foo.&bar // reference to foo cls(3) // call by overload detected cls([1,5,7]) cls(1,2) def benchmark(repeat, Closure alg) { start = System.currentTimeMillis(); repeat.times { alg(it) } return System.currentTimeMillis() - start } slow = benchmark(10000) { (int) it / 2 } fast = benchmark(10000, { it.intdiv(2) }) // intdiv is faster than / System.out.println("slow - fast = " + (slow - fast)) // output: slow - fast = 20 // default value def inc = { x, i = 1 -> return x + i } println inc(3) // output: 4 println inc(5, 2) // output: 7
6.2 闭包自身的方法
还记得C++的函数适配器吗?groovy也提供了这样的方法为Closer:curry(),可接受一个或多个参数。
之前已经看到了isCase方法,以进行分类。
def multiply = { x, y -> return x * y } multiply.getParameterTypes().size() // result: 2 def double_ = multiply.curry(2) println double_(3) // output: 6 [1, 2, 8, 7, 3].grep { it % 2 == 0 } // result: [2, 8] switch(8) { case { it > 3 } : println "> 3" // output: > 3 }
6.3 从闭包返回结果
闭包有两种返回结果的方式:
a. 返回最后一个表达式执行的结果,在这种情况下return是可以省略的;
b. 从闭包的任何地方返回,注意这种返回的意思是,本次计算结束,也就意味着如果闭包用在循环中,下次的循环的元素将继续被调用;
[1, 2, 3].collect { it * 2 } // same as: return it * 2,result: [2, 4, 6] [1, 2, 3].collect { if ( it % 2 == 0) return it * 2 // end current computing return it } // result: [1, 4, 3]