http://www.ruby-cn.org/
可以參見http://martinfowler.com/bliki/Closures.html
塊(block):隻是一段代碼,相當于一個匿名函數;閉包(Closures):一段代碼,能作為參數傳遞給其它方法。
讓我們再回來看看自動點唱機,某些時候,我們需要處理點唱機和使用者的界面:很多按鈕,供使用者選擇歌曲和控制播放,我們需要給這些按鈕指定相應的時間處理代碼,而Ruby中的block就很适合幹這樣的事情。假設點唱機的設計者通過Ruby擴充為我們提供了一個基本的按鈕類。
|
當使用者按下按鈕之後如何處理呢?Button類提供了一個
buttonPressed
方法,在按鈕按下時能被回調。是以最簡單的方法建立Button的子類,然後在每個子類中實作
buttonPressed
方法。
bStart = StartButton.new |
這樣做有兩個問題,首先這樣将産生大量子類,如果Button變化了,所有子類都需要維護;第二,按鈕按下之後需要執行的行為不應該在按鈕上表示,這是點唱機的責任。我們可以用塊來消除這些問題
|
上面代碼的關鍵點在
JukeboxButton#initialize
的第二個參數,這個參數前面帶有一個&符号,在Ruby中代表這個參數是一個塊,這個塊将會被轉化為一個Proc對象,并關聯道相應變量。在本例中我們把它賦給執行個體變量
@action 。
當回調方法
buttonPressed
執行時,我們用方法
Proc#call
來調用相應的block。
當建立一個Proc對象之後我們得到的是什麼呢?很有趣,我們得到的不僅是一串代碼。和這個block定義相關聯的上下文環境(範圍内的):self值,定義它的方法,變量,常量等。Ruby中的一個有趣的地方就是即使block定義時候的變量已經不在它的使用範圍内,這個變量還保留着,仍可以使用
我們來看一個例子,這個例子用了方法proc,這個方法把一個block變為了一個Proc對象。
| ||
| ||
| ||
| ||
| » | |
| » | |
| ||
| » | |
方法
nTimes
傳回一個Proc對象,這個對象引用了這個函數的參數:
aThing
。
即使這個參數在塊被調用時已經不在自己的作用域裡了,這個塊還是可以通路這個參數。(比如
p1.call(4),
這個時候,雖然對p1的指派語句中的參數23已經超出了作用域範圍,但是它仍然儲存着23×4=92。)