是的,一开始有点疑惑。
在 Ruby 中,方法可以接收代码块以执行任意代码段。
当一个方法需要一个块时,您可以通过调用yield 函数来调用它。
例子:
以Person 为例,该类具有name 属性和do_with_name 方法。当方法被调用时,它会将name 属性传递给块。
class Person
def initialize( name )
@name = name
end
def do_with_name # expects a block
yield( @name ) # invoke the block and pass the `@name` attribute
end
end
现在您可以调用此方法并传递任意代码块。
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
将打印:
Got: Oscar
请注意,该块接收一个名为value 的变量作为参数。当代码调用yield 时,它会将@name 的值作为参数传递。
yield( @name )
可以用不同的块调用相同的方法。
例如颠倒名称:
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
=> "racsO"
其他更有趣的现实生活示例:
过滤数组中的元素:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
=> ["Tuesday", "Thursday"]
或按名称长度排序:
days.sort do |x,y|
x.size <=> y.size
end
=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]
如果该块是可选的,您可以使用:
yield(value) if block_given?
如果不是可选的,只需调用它。
您可以在您的计算机上使用irb (Interactive Ruby Shell) 尝试这些示例
以下是复制/粘贴形式的所有示例:
class Person
def initialize( name )
@name = name
end
def do_with_name # expects a block
yield( @name ) # invoke the block and pass the `@name` attribute
end
end
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
# Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
# Sort by name length:
days.sort do |x,y|
x.size <=> y.size
end