发布于2026-06-29 阅读(0)
扫一扫,手机访问
block是什么?

在Ruby里,“block”这个词你应该经常遇到。官方给出的定义是“一段被包裹着的代码”——坦白讲,看完这个定义,大多数人还是云里雾里。不如换个更直白的说法:block就像一段代码片段,可以被塞进一个变量里,随时随地拿出来跑。
光讲理论有点干,咱们直接看代码,从最基础的加法开始,一步步把它改造成block的形式,感受会更直观。
比如,对两个数做加法?
puts 5 + 6 # => 11
这样写当然没问题,但它只满足了block定义的前半部分——它是一段代码。可它没有被“包裹”起来,也没有存进变量。所以咱们继续改造,先让它更通用一点。
a = 5 b = 6 puts a + b # => 11
好,用变量代替了数字,代码具备了通用性,但依然没有存进变量。现在咱们来实现真正的block。
addition = lambda { |a, b| return a+b }
puts addition.call(5, 6)
# => 11
看看,现在它被好好地包裹了起来,这就是一个block!lambda是Ruby里创建block最常用的方式,还有别的方法,不过先不展开。
这时候你可能会想:“等等,这不就是一个方法(method)吗,只是少了类和对象。” 没错,你可以把block理解为一个不绑定任何对象的方法。
一个block包含一块代码,你可以给它起个名字(通过变量),也可以直接传递。block的代码一律包裹在花括号{}或者do...end里。
[1, 2, 3].each do |i| puts i end #=> 1 2 3
上面这个例子,each方法后面跟着do...end,那就是一个block。
Ruby里任何一个方法都可以接受一个block。
def test;end
test{ puts i}
def test
yield
end
test{puts "hello test!"}
def test(x)
yield(x)
end
test('world!'){|x| puts "hello #{x}"}
yield关键字不仅能挂载block,还能给block传参数。
def test(&block)
block.call("world")
end
test{|msg| puts "hello #{msg}"}
这个block传进方法后,被&转成了一个Proc对象。
def test(&block)
inner_test(&block)
end
def inner_test
yield("haha!")
end
test{|msg| puts "hello #{msg}"}
test方法把block转为Proc,内部的inner_test又用&把这个Proc转回block——灵活得很。
当然,和Ruby里其他东西一样,block也是对象。
empty_block = lambda { }
puts empty_block.object_id
# => 28765760
puts empty_block.class
# => Proc
puts empty_block.class.superclass
# => Object
你看,这个block有object_id,属于Proc类(Ruby对block的称呼),而Proc的父类就是Object。
我们甚至可以反过来:从一个方法(method)生成block。说到底,方法就是绑定了某个对象的block,可以访问那个对象的状态。下面演示用方法创建block——请原谅糟糕的对象建模。
class Calculator def add(a, b) return a+b end end puts Calculator.new.add(5, 6) # => 11
这段当然能正常工作。现在稍作修改:
class Calculator
def add(a, b)
return a+b
end
end
addition_method = Calculator.new.method("add")
addition = addition_method.to_proc
puts addition.call(5, 6)
# => 11
瞧,一个传统的方法就这样被转换成了block!
咱们来构造4个block,分别做加、减、乘、除。每个block接收两个参数,执行运算并返回结果。
Addition = lambda { |a, b| return a+b }
Subtraction = lambda { |a, b| return a-b }
Multiplication = lambda { |a, b| return a*b }
Division = lambda { |a, b| return a/b }
# 使用的时候通过call来使用
Addition.call(5, 6)
# => 11
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8