我們來簡單地描述Ruby的一個(gè)獨(dú)特特性。Block,一種可以和方法調(diào)用相關(guān)聯(lián)的代碼塊,幾乎就像參數(shù)一樣。這是一個(gè)不可思議的功能強(qiáng)大的特性。
可以用Block實(shí)現(xiàn)回調(diào)(但它比Java的匿名內(nèi)部(anonymous inner)類更簡單),傳遞一組代碼(但它遠(yuǎn)比c的函數(shù)指針靈活),以及實(shí)現(xiàn)迭代器。
Block只是在花括號或者do...end之間的一組代碼。
{puts "Hello"} #this is a block
do ###
club.enroll(person) #and so is this
person.socialize #
end ###
為什么有兩種分界符?部分原因是有人覺得有時(shí)候用一種分界符比另外一種感覺更自然。另外一部分原因是它們有不同的優(yōu)先級:花括號比do/end綁定的更緊密些。我們嘗試遵循正在成為Ruby標(biāo)準(zhǔn)的一個(gè)約定俗成,單行block用花括號,多行block用do/end。
一旦創(chuàng)建了block,就可以與方法的調(diào)用相關(guān)聯(lián)。把block的開始放在含有方法調(diào)用的源碼行的結(jié)尾處,就可以實(shí)現(xiàn)關(guān)聯(lián)。比如,在下面的代碼中,含有puts "Hi" 的block與greet方法的調(diào)用相關(guān)聯(lián)。
如果方法有參數(shù),它們出現(xiàn)在block之前。
verbose_greet("Dave","loyal customer"){puts "Hi"}
然后使用Ruby的yield語句,方法可以一次或多次地調(diào)用(invoke)相關(guān)聯(lián)的block??梢园褃ield想象成比如方法調(diào)用,它調(diào)用含有yield語句的方法所關(guān)聯(lián)的block。
下面的例子顯示了如何使用yield語句。定義了一個(gè)方法,它會調(diào)用yield兩次。然后調(diào)用這個(gè)方法,把block放在同一行,在方法調(diào)用之后(并在方法的所有參數(shù)之后)。
def call_block
puts "Start of method"
yield
yield
puts "End of method"
end
call_block{puts "In the block"}
輸出結(jié)果:
Strat of method
In the block
In the block
End of method
可以提供參數(shù)給yield的調(diào)用;參數(shù)會傳遞到block中。在block中,豎線(|)之間給出參數(shù)名來接受這些來自yield的參數(shù)。
def call_block
yield("Hello",99)
end
call_block {|str,num| ...}
在Ruby庫中大量使用了block來實(shí)現(xiàn)迭代器;迭代器是從某種收集(collection)如數(shù)組中連續(xù)返回元素的方法。
animals = %w(ant bee cat dog elk) #創(chuàng)建一個(gè)數(shù)組
animals.each{|animal| puts animal} #迭代它的內(nèi)容
輸出結(jié)果:
讓我們看一下如何實(shí)現(xiàn)應(yīng)用在前面例子中的Array類中的each迭代器。each迭代器循環(huán)處理數(shù)組中的元素,對每個(gè)元素調(diào)用yield。在偽碼中,它可能寫成:
#在Array類中......
def each
for each element #--無效的Ruby語句
yield(element)
end
end
許多內(nèi)建于c和java等語言的循環(huán)結(jié)構(gòu)在Ruby中只是方法調(diào)用,這些方法會零次或多次地調(diào)用相關(guān)聯(lián)的block。
['cat','dog','horse'].each{|name| print name," "}
5.times {print "*"}
3.upto(6){|i| print i}
('a'..'e').each{|char| print char}
輸出結(jié)果:
cat dog horse *****3456abcde
上面的代碼要求對象5 五次調(diào)用block;然后要求對象3調(diào)用一個(gè)block,并傳入一個(gè)連續(xù)的值,直到這個(gè)值到達(dá)6為止。最后對a到e的字符區(qū)間(range),使用each方法調(diào)用block。
您可能感興趣的文章:- 舉例講解Ruby中迭代器Iterator的用法
- 簡要說明Ruby中的迭代器
- Ruby迭代器的7種技巧分享
- Ruby中的迭代器詳解
- js 數(shù)組實(shí)現(xiàn)一個(gè)類似ruby的迭代器
- ruby 迭代器使用方法
- Ruby 迭代器知識匯總