Groovy中,function和closure非常相似,不过还是有区别,通过示例来说明。
1)函数体内不能访问上下文中通过def定义的变量
a = 32 //def keyword not used for this one, 这个变量可以在下面的函数中访问到
def c = 'there', d = 'yonder'
def f(){
assert a == 32 //outer 'a' visible because 'def' keyword wasn't used with it
def c = 'here'
//compiles OK because other defined c invisible inside function definition
//println d //a compile error when uncommented: d not accessable
c
}
assert f() == 'here' //syntax to invoke a function
2)定义函数的时候,def关键字不能省略。
def f(){
a = 1
c = { 'here, again' }
c()
}
assert f() == 'here, again'
//g(){ println 'there, again' }
//a compile error when uncommented: def keyword required
注:也可以把一个函数定义赋值给另一个函数名:
def f(){ 77 } //define function using name 'f'
assert f() == 77
def g = this.&f //special syntax to assign function to another variable
assert g() == 77
def h = g //don't use special syntax here
assert h() == 77
f = 'something else' //this 'f' is a VARIABLE, not the function NAME
assert f() == 77 //the function name can't be reassigned
3)函数定义不能嵌套,即一个函数或块中,不能进行函数定义。
def f(){
//def g1(){ println 'there' }
//a compile error when uncommented: can't nest functions
'here'
}
assert f() == 'here'
try{
//def g2(){ println 'yonder' }
//a compile error when uncommented: can't nest functions
}
c = {
//def g3(){ println 'outer space' }
//a compile error when uncommented: can't nest functions
}
def h(){
try{ def c = { 'here, again' } }
//we can have blocks and closures within functions
}
4)函数参数方面,函数同样可以有参数,但与Closure略有不同,函数参数能力更强些:
def foo( list, value ){
list << value
}
x = []
foo(x, 1)
foo(x, 2)
assert x == [1, 2]
函数可以做到多态定义,即用一个名字,不同的参数,来定义不同的函数。
def foo(value){ 'v1' }
def foo(list, value){ 'v2' }
assert foo(9) == 'v1'
assert foo([], 1) == 'v2'
函数返回值和Closure类似,不过通过void前缀来定义的函数,返回总是null
def f1(){ 7 }
assert f1() == 7 //value of last statement is returned
def f2(){ return 8; 3 }
assert f2() == 8 //return explicitly using return
void f3(){ 10 }
assert f3() == null //null always returned
//void f4(){ return 9 }
//a compile error when uncommented: can't use 'return' in a void function
5)函数名字优先于Closeure变量名字。
def c(){'method c'}
def c= {-> 'closure c'}
assert c() == 'method c'
def d(i){'method d'}
def d= {'closure d'}
assert d(9) == 'method d'
6)和Closures类似,当参数是closure时,函数调用也可以采用直观的简写形式:
def f(Closure c){ c() }
assert f{ 'heehee' } == 'heehee'
7)函数的参数可以支持缺省值,当然仅限于后面的参数
def dd( a, b=2 ){ "$a, $b" }
assert dd( 7, 4 ) == '7, 4'
assert dd( 9 ) == '9, 2'
8)函数的参数可以实现命名传递,注意总是使用第一个参数,作为map
def f(m, i, j){ i + j + m.x + m.y }
assert f(6,x:4, y:3,7) == 20
def g(m, i, j, k, c){ c(i + j + k, m.x + m.y) }
assert g(y:5, 1, 2, x:6, 3){a,b-> a * b } == 66
7)函数可以通过最后一个参数Object[] 来支持动态参数
def c( arg, Object[] extras ){
def list= []
list<< arg
extras.each{ list<< it }
list
}
assert c( 1 ) == [ 1 ]
assert c( 1, 2, 3, 4 ) == [ 1, 2, 3, 4 ]
8)函数对于List类型的参数,也进行了特殊关照,可以自动拆开来使用
def x(a, b, c){a + b + c}
def list=[1,2,3]
assert x(list) == 6
9)函数可以递归调用
def gcd( m, n ){ if( m%n == 0 )return n; gcd(n,m%n) }
assert gcd( 28, 35 ) == 7
概括起来,Closeure更加直观灵活,而函数功能更规范,相对功能更强些。