groovy简明教程(四)闭包

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]

6.4 闭包的变量作用域

 关于变量的作用域,理解内部类就很容易理解了。我直接引用书上的一个例子,因为想不出更好的例子了。

注意:书上的一个错误:

class Mother {
    int field = 1
    int foo() {
        return 2
    }
    Closure birth (param) {
        def local = 3
        def closure = { caller ->
            [ this, field, foo(), local, param, caller, owner ] // error in book: this.owner
        }
        return closure
    }
}

Mother julia = new Mother()
closure = julia.birth(4)
context = closure.call(this)
println context[0] == julia // output: ture

println context[1..4] // output: [1, 2, 3, 4]
println context[5] instanceof Script // output: true
println context[6] == julia // output: true

firstClosure = julia.birth(4)
secondClosure = julia.birth(4)
println firstClosure.is(secondClosure) // output: false

 特别要注意到是最后一个输出false,每次调用birth都生成了一新的Closure对象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值