閉包是可以用作函數參數和方法參數的代碼塊。一直以來,這種編程結構都是一些語言(如 Lisp、Smalltalk 和 Haskell)的重要組成部分。盡管一些頗具競爭力的語言(如 C#)采納了閉包,但 java 社區至今仍抵制對它的使用。本文探討閉包在為編程語言帶來一點點便利的同時是否也帶來不必要的復雜性、閉包還有無更多的益處。
10 年前,我剛剛開始山地自行車運動的時候,我更愿意選用零件盡可能少盡可能簡單的自行車。稍后,我意識到一些零件(如后減震器)可以保護我的背部和我自行車的框架在德克薩斯州高低起伏的山區中免受損害。我于是可以騎得更快,出問題的次數也漸少。雖然隨之帶來了操作上的復雜性和維護需求的增加,但對于我來說這點代價還是值得的。
在 跨越邊界系列 文章中,作者 BrUCe Tate 提出這樣一種觀點,即當今的 Java 程序員們通過學習其他方法和語言很好地武裝了自己。自從 Java 技術明顯成為所有開發項目的最佳選擇以來,編程前景得以改變。其他框架影響著 Java 框架的構建方式,您從其他語言中學到的概念也可以影響 Java 編程。您編寫的 Python(或 Ruby、Smalltalk 等語言)代碼可以改變編寫 Java 代碼的方式。
本系列介紹與 Java 開發完全不同的編程概念和技術,但是這些概念和技術也可以直接應用于 Java 開發。在某些情況下,需要集成這些技術來利用它們。在其他情況下,可以直接應用這些概念。具體的工具并不那么重要,重要的是其他語言和框架可以影響 Java 社區中的開發人員、框架,甚至是基本方式。
關于閉包這個問題,Java 愛好者們現在陷入了類似的爭論中。一些人認為閉包帶給編程語言的額外復雜性并不劃算。他們的論點是:為了閉包帶來的一點點便利而打破原有語法糖的簡潔性非常不值得。其他一些人則認為閉包將引發新一輪模式設計的潮流。要得到這個問題的最佳答案,您需要跨越邊界,去了解程序員在其他語言中是如何使用閉包的。
Ruby 中的閉包
閉包是具有閉合作用域 的匿名函數。下面我會具體解釋每個概念,但最好首先對這些概念進行一些簡化。閉包可被視作一個遵循非凡作用域規則且可以用作參數的代碼塊。我將使用 Ruby 來展示閉包的運行原理。用 irb 命令啟動解釋程序,然后用 load filename 命令加載每個樣例。清單 1 是一個最簡單的閉包:
3.times {puts "Inside the times method."}Results:Inside the times method.Inside the times method.Inside the times method.
times
是作用在對象 3
上的一個方法。它執行三次閉包中的代碼。{puts "Inside the times method."}
是閉包。它是一個匿名函數,times
方法被傳遞到該函數,函數的結果是打印出靜態語句。這段代碼比實現相同功能的 for
循環(如清單 2 所示)更加緊湊也更加簡單:
for i in 1..3 puts "Inside the times method."end
Ruby 添加到這個簡單代碼塊的第一個擴展是一個參數列表。方法或函數可通過傳入參數與閉包通信。在 Ruby 中,使用在 字符之間用逗號隔開的參數列表來表示參數,例如
argument, list
。用這種方法使用參數,可以很輕易地在數據結構(如數組)中構建迭代。清單 3 顯示了在 Ruby 中對數組進行迭代的一個例子:
['lions', 'tigers', 'bears'].each {item puts item}Results: lionstigersbears
each
方法用來迭代。您通常想要用執行結果生成一個新的集合。在 Ruby 中,這種方法被稱為 collect
。您也許還想在數組的內容里添加一些任意字符串。清單 4 顯示了這樣的一個例子。這些僅僅是眾多使用閉包進行迭代的方法中的兩種。
animals = ['lions', 'tigers', 'bears'].collect {item item.upcase}puts animals.join(" and ") + " oh, my."LIONS and TIGERS and BEARS oh, my.
新聞熱點
疑難解答