Ruby 在语法上对文字匿名过程(在 Ruby 中称为 blocks)提供轻量级支持。因此,它不需要为此添加新的语言功能。
因此,您通常所做的就是编写一个方法,该方法获取一段代码,分配资源,在该资源的上下文中执行该代码块,然后关闭该资源。
类似这样的:
def with(klass, *args)
yield r = klass.open(*args)
ensure
r.close
end
你可以这样使用它:
with File, 'temp.txt', 'w' do |f|
f.write 'hi'
raise 'spitespite'
end
但是,这是一种非常程序化的方法。 Ruby 是一种面向对象的语言,这意味着在File 的上下文中正确执行代码块的责任应该属于File 类:
File.open 'temp.txt', 'w' do |f|
f.write 'hi'
raise 'spitespite'
end
这可以这样实现:
def File.open(*args)
f = new(*args)
return f unless block_given?
yield f
ensure
f.close if block_given?
end
这是一种通用模式,由 Ruby 核心库、标准库和第三方库中的许多类实现。
与通用 Python 上下文管理器协议更接近的对应关系是:
def with(ctx)
yield ctx.setup
ensure
ctx.teardown
end
class File
def setup; self end
alias_method :teardown, :close
end
with File.open('temp.txt', 'w') do |f|
f.write 'hi'
raise 'spitespite'
end
请注意,这与 Python 示例几乎没有区别,但它不需要为语言添加新语法。