随笔-30  评论-123  文章-0  trackbacks-0

在用Java编程时,大部分可执行的代码要么被封装在静态类方法(static class methods)中,要么被封装在实例方法(nstance methods)中(代码 也可以被封装在构造函数,初始化函数或初始化表达式中,但这些在这儿不重要).方法把代码封装在一对花括号里并给代码段分配一个方法名.所有 这些方法必须定义在某种类型的类里面.例如,假设你要写一个返回任意整数平方的方法,这个方法可以这样写:

package  example.math;

public   class  MyMath 
{
   
public   static   long  square( int  numberToSquare)
{
        
return  numberToSquare  *
 numberToSquare;
   }

}
要使用square()方法,你需要像下面一样引用类和方法
import example.math.MyMath;



int x, y;
= 2;
= example.math.MyMath.square(x);

// y = 4.

使用Groovy你也能完成上面的工作,不过在Groovy里面你不需要声明任何类和方法.这一切由闭包来完成.闭包是封装在花括号中的一条或几条程 序语句.闭包和方法的最大区别在于闭包不需要类和方法名.下面的代码将square()方法重写为一个闭包.
{numberToSquare ->
     numberToSquare 
* numberToSquare
}
;

正如你所看到的,除了不需要声明类和分配给代码方法名.然而要说明的是,上面的例子还不能用因为没有使用闭包的方法.没有标识(方法名)我 们怎么调用这个闭包呢?方法是:把创建的闭包赋给一个变量,那么你就可以使用这个变量作为闭包的标识来调用这个闭包.
// 初始化变量
int x, y;
= 2;

// 创佳闭包并把它赋给变量C
def c = {numberToSquare -> numberToSquare * numberToSquare }

// 使用变量C作为闭包的标识, 调用闭包
= c.call(x);

// y = 4

闭包真正优越的地方是你可以创建闭包并把它赋给一个变量,并且可以像其他变量一样在整个程序中传递.刚开始,你可能觉得这没什么,几乎毫 无用处,但是随着你学习的深入,你会发现在Groovy里闭包无处不在.

举个例子,我们用Groovy来扩展java.util.Vector类.我们添加一个方法到Vector类里,这个方法允许你应用闭包操作向量中的所有成员.我们新建 一个类GVector如下,

package  example;

public   class  GVector  extends  java.util.Vector  {

  
public  GVector() {
      
super ();
  }


  
public   void  apply( c ) {
     
for  (i in  0 .. < size()) {
        
this [i]  =  c( this [i]);
     }

  }

}

apply()方法获得一个闭包作为输入参数,对于GVector中的每一个元素,闭包被调用传递这个元素,返回的结果值用来替换这个元素.这个思想就 是你可以使用闭包来修改GVector中的内容,这个闭包必须能够获取元素并把它转换成别的什么.
现在我们就可以调用apply()方法了.你可以传递任意你需要的闭包给apply().例如我们新建一个GVector,设置几个元素,然后将这些元素传递给
我们上面创建的那个能计算整数平方的闭包.

example.GVector gVect  =   new  example.GVector();
gVect.add(
2 );
gVect.add(
3 );
gVect.add(
4 );

=   {numberToSquare  ->  numberToSquare  *  numberToSquare;}

gVect.apply(c);

//  GVector中的所有元素全部被平方了.
由于apply()中的闭包可以是任意的,因此你可以把任何闭包传递给apply().例如使用下面的这个闭包简单地把传递给它的元素打印出来.
example.GVector gVect = new example.GVector();
gVect.add(
2);
gVect.add(
3);
gVect.add(
4);

c2 
= {value -> println(value);}

gVect.apply(c2);

// GVector中的元素全部被打印出来.
假设你已经定义并编译了GVector这个类,那么当你运行上面的脚本时,将得到下面的结果:
C:/> groovy myscript.groovy
4
9
16
C:
/>
除了把闭包赋值给变量,你也可以直接把它声明为方法的参数.例如,上面的代码可以重写为如下形式:
example.GVector gVect = new example.GVector();
gVect.add(
2);
gVect.add(
3);
gVect.add(
4);

gVect.apply 
{value -> println(value);}

// GVector中的元素全部被打印出来.

这段代码的功能和前面的功能一样,只不过闭包被直接定义为apply()方法的参数.

闭包VS代码段

闭包看上去就像正规的Java或Groovy代码段,但是实际上他们并不相同.正规代码段里的代码一旦遇到就由虚拟机来执行,闭包中花括号里的代
码直到call()被调用时才被执行.上面的例子中,闭包在程序行中定义,但是当时并不执行.只有闭包明确的调用call()时才会被执行.这是闭包和 代码段的重要区别.也许他们看上去很像,但事实上两者不同.正规的Java或Groovy代码当遇到时就执行,;而闭包当且仅当call()被调用时才被 执行. 

            to be continue...
posted on 2006-04-26 17:05 学二的猫 阅读(2499) 评论(4)  编辑  收藏 所属分类: Groovy

评论:
# re: Groovy指南--(2) 闭包(非正式) 2006-04-26 22:52 | 指教了
不是你写的吧?“正规代码段里的代码一旦执行到就由虚拟机来执行”,“正规的Java或Groovy代码在执行到时就执行”,这些话是不是有点repeat废话?呵呵  回复  更多评论
  
# re: Groovy指南--(2) 闭包(非正式) 2006-04-26 22:52 | 指教了
不是你写的吧?“正规代码段里的代码一旦执行到就由虚拟机来执行”,“正规的Java或Groovy代码在执行到时就执行”,这些话是不是有点repeat废话?呵呵  回复  更多评论
  
# re: Groovy指南--(2) 闭包Closure(非正式) 2006-04-27 08:56 | 学二的猫
@指教了
这不是我写的,我翻译自Groovy官方网站.
呵呵,让大家见笑了.翻译的是有点业余:)
谢谢给出批评意见,指出翻译错误.上面你提到的我已经修改了.
再次谢谢大家...
  回复  更多评论
  
# re: Groovy指南--(2) 闭包Closure(非正式) 2008-03-20 11:26 | 赵斌
还是不错,让我对闭包有了一个初步的理解。
谢谢!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: