隨筆-30  評論-123  文章-0  trackbacks-0

          在用Java編程時,大部分可執(zhí)行的代碼要么被封裝在靜態(tài)類方法(static class methods)中,要么被封裝在實(shí)例方法(nstance methods)中(代碼 也可以被封裝在構(gòu)造函數(shù),初始化函數(shù)或初始化表達(dá)式中,但這些在這兒不重要).方法把代碼封裝在一對花括號里并給代碼段分配一個方法名.所有 這些方法必須定義在某種類型的類里面.例如,假設(shè)你要寫一個返回任意整數(shù)平方的方法,這個方法可以這樣寫:

          package ?example.math;

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

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



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

          //?y?=?4.

          使用Groovy你也能完成上面的工作,不過在Groovy里面你不需要聲明任何類和方法.這一切由閉包來完成.閉包是封裝在花括號中的一條或幾條程 序語句.閉包和方法的最大區(qū)別在于閉包不需要類和方法名.下面的代碼將square()方法重寫為一個閉包.
          {numberToSquare?->
          ?????numberToSquare?
          *?numberToSquare
          }
          ;

          正如你所看到的,除了不需要聲明類和分配給代碼方法名.然而要說明的是,上面的例子還不能用因?yàn)闆]有使用閉包的方法.沒有標(biāo)識(方法名)我 們怎么調(diào)用這個閉包呢?方法是:把創(chuàng)建的閉包賦給一個變量,那么你就可以使用這個變量作為閉包的標(biāo)識來調(diào)用這個閉包.
          //?初始化變量
          int?x,?y;
          x?
          =?2;

          //?創(chuàng)佳閉包并把它賦給變量C
          def?c?=?{numberToSquare?->?numberToSquare?*?numberToSquare?}

          //?使用變量C作為閉包的標(biāo)識,?調(diào)用閉包
          y?=?c.call(x);

          //?y?=?4

          閉包真正優(yōu)越的地方是你可以創(chuàng)建閉包并把它賦給一個變量,并且可以像其他變量一樣在整個程序中傳遞.剛開始,你可能覺得這沒什么,幾乎毫 無用處,但是隨著你學(xué)習(xí)的深入,你會發(fā)現(xiàn)在Groovy里閉包無處不在.

          舉個例子,我們用Groovy來擴(kuò)展java.util.Vector類.我們添加一個方法到Vector類里,這個方法允許你應(yīng)用閉包操作向量中的所有成員.我們新建 一個類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()方法獲得一個閉包作為輸入?yún)?shù),對于GVector中的每一個元素,閉包被調(diào)用傳遞這個元素,返回的結(jié)果值用來替換這個元素.這個思想就 是你可以使用閉包來修改GVector中的內(nèi)容,這個閉包必須能夠獲取元素并把它轉(zhuǎn)換成別的什么.
          現(xiàn)在我們就可以調(diào)用apply()方法了.你可以傳遞任意你需要的閉包給apply().例如我們新建一個GVector,設(shè)置幾個元素,然后將這些元素傳遞給
          我們上面創(chuàng)建的那個能計(jì)算整數(shù)平方的閉包.

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

          c?
          = ? {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中的元素全部被打印出來.
          假設(shè)你已經(jīng)定義并編譯了GVector這個類,那么當(dāng)你運(yùn)行上面的腳本時,將得到下面的結(jié)果:
          C:/>?groovy?myscript.groovy
          4
          9
          16
          C:
          />
          除了把閉包賦值給變量,你也可以直接把它聲明為方法的參數(shù).例如,上面的代碼可以重寫為如下形式:
          example.GVector?gVect?=?new?example.GVector();
          gVect.add(
          2);
          gVect.add(
          3);
          gVect.add(
          4);

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

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

          這段代碼的功能和前面的功能一樣,只不過閉包被直接定義為apply()方法的參數(shù).

          閉包VS代碼段

          閉包看上去就像正規(guī)的Java或Groovy代碼段,但是實(shí)際上他們并不相同.正規(guī)代碼段里的代碼一旦遇到就由虛擬機(jī)來執(zhí)行,閉包中花括號里的代
          碼直到call()被調(diào)用時才被執(zhí)行.上面的例子中,閉包在程序行中定義,但是當(dāng)時并不執(zhí)行.只有閉包明確的調(diào)用call()時才會被執(zhí)行.這是閉包和 代碼段的重要區(qū)別.也許他們看上去很像,但事實(shí)上兩者不同.正規(guī)的Java或Groovy代碼當(dāng)遇到時就執(zhí)行,;而閉包當(dāng)且僅當(dāng)call()被調(diào)用時才被 執(zhí)行.?

          ????????????to be continue...
          posted on 2006-04-26 17:05 學(xué)二的貓 閱讀(2560) 評論(4)  編輯  收藏 所屬分類: Groovy

          評論:
          # re: Groovy指南--(2) 閉包(非正式) 2006-04-26 22:52 | 指教了
          不是你寫的吧?“正規(guī)代碼段里的代碼一旦執(zhí)行到就由虛擬機(jī)來執(zhí)行”,“正規(guī)的Java或Groovy代碼在執(zhí)行到時就執(zhí)行”,這些話是不是有點(diǎn)repeat廢話?呵呵  回復(fù)  更多評論
            
          # re: Groovy指南--(2) 閉包(非正式) 2006-04-26 22:52 | 指教了
          不是你寫的吧?“正規(guī)代碼段里的代碼一旦執(zhí)行到就由虛擬機(jī)來執(zhí)行”,“正規(guī)的Java或Groovy代碼在執(zhí)行到時就執(zhí)行”,這些話是不是有點(diǎn)repeat廢話?呵呵  回復(fù)  更多評論
            
          # re: Groovy指南--(2) 閉包Closure(非正式) 2006-04-27 08:56 | 學(xué)二的貓
          @指教了
          這不是我寫的,我翻譯自Groovy官方網(wǎng)站.
          呵呵,讓大家見笑了.翻譯的是有點(diǎn)業(yè)余:)
          謝謝給出批評意見,指出翻譯錯誤.上面你提到的我已經(jīng)修改了.
          再次謝謝大家...
            回復(fù)  更多評論
            
          # re: Groovy指南--(2) 閉包Closure(非正式) 2008-03-20 11:26 | 趙斌
          還是不錯,讓我對閉包有了一個初步的理解。
          謝謝!  回復(fù)  更多評論
            
          主站蜘蛛池模板: 十堰市| 民县| 孙吴县| 南丹县| 伊川县| 白河县| 宁河县| 玉龙| 嵊泗县| 盱眙县| 金华市| 临清市| 永定县| 博爱县| 罗田县| 龙南县| 综艺| 策勒县| 黑水县| 讷河市| 阿合奇县| 高雄县| 金沙县| 鸡西市| 毕节市| 柏乡县| 留坝县| 宝应县| 湄潭县| 四子王旗| 神农架林区| 牡丹江市| 高阳县| 梁平县| 仁布县| 腾冲县| 扎囊县| 称多县| 台东县| 乳源| 察隅县|