阳光不锈

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
代码块:可以和方法调用关联的一系列代码,就好像这些代码是方法的参数一样,这是一个令人难以置信的强大特性。你可以使用代码块实现回调(但不像Java的匿名内部类那么简单),传递一系列代码(但要比C的函数指针更加复杂),和实现迭代器。

代码块是用大括号或者do...end括起来的一系列代码。
{ puts "Hello" }       # 这是一个代码块

do                           #
  club.enroll(person)        # 这也是代码块
  person.socialize           #
end

一旦你创建了一个代码块,就可以把它和一个方法调用关联在一起。那个方法能够调用代码块一次或者更多次,Ruby的yield语句。下面的例子显示了这个过程。我们定义一个方法,这个方法调用yield两次。然后我们调用这个方法,把代码块放在同一行中方法调用的后面(也是方法的所有参数的后面)。[有些人喜欢把和方法关联的代码块当作是一种传递过来的参数。它们虽然是一个级别的,但这没有显示出所有的内涵。最好把代码块和方法当成是协同工作的关系,在它们之间控制在来回交换。]
def callBlock
  yield
  yield
end

callBlock { puts "In the block" }

结果:
In the block
In the block

看看代码块中的代码(puts "In the block") 是如何被执行两次的,就是对yield的每一次调用。

你可以在调用yield时给出参数,这些参数传递给代码块。在代码块中,列举变量的名字来接受参数,这些参数被用"|"括着。

  def callBlock
    yield , 
  end

  callBlock { |, | ... }


代码块贯穿在实现迭代器的Ruby库中,迭代器就是一种方法,用来连续返回某种集合的元素,比如一个数组。
a = %w( ant bee cat dog elk )    # 创建一个数组
a.each { |animal| puts animal }  # 迭代所有的内容
 
produces: 
ant
bee
cat
dog
elk

我们来看看实现Array类的each迭代器的可能的方法,我们要用到前面的例子。each迭代器遍历数组的每个元素,每次都调用yield,类似的代码可能会是下面这样:
# 在Array类中...
def each
  for each element
    yield(element)
  end
end


这样你就可以使用数组的each方法来迭代数组元素提供给代码块,代码块依次在每个元素返回时被调用一次。

[ 'cat', 'dog', 'horse' ].each do |animal|
  print animal, " -- "
end

结果:
cat -- dog -- horse --


类似的,内置在语言比如C或者Java中的许多循环结构在Ruby中就是简单的方法调用,这个方法调用所关联的代码块0次或者更多次。
5.times {  print "*" }
3.upto(6) {|i|  print i }  //puts是每打印一个就有回车的,print没有
('a'..'e').each {|char| print char }

结果: 
*****3456abcde


在这里,我们让数字5调用一个代码块5次,然后让数字3调用一个代码块,传递给它连续的数值直到6,最后,字符"a"到"e"的区间使用each方法调用一个块。
posted on 2009-05-04 16:59  靳小透  阅读(237)  评论(0编辑  收藏  举报