扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:中国IT实验室 来源:中国IT实验室 2007年9月30日
关键字:
在本页阅读全文(共2页)
用闭包进行定制
您已经知道如何使用现成的闭包。Ruby 让您也可以编写使用自己的闭包的方法。这种自由的形式意味着 Ruby API 的代码会更加紧凑,因为 Ruby 不需要在代码中定义每个使用模型。您可以根据需要通过闭包构建自己的抽象概念。例如,Ruby 的迭代器数量有限,但该语言没有迭代器也运行得很好,这是因为可以通过闭包在代码中构建您自己的迭代概念。
要构建一个使用闭包的函数,只需要使用 yield
关键字来调用该闭包。清单 6 是一个例子。paragraph
函数提供第一句和最后一句输出。用户可以用闭包提供额外的输出。
清单 6. 构建带有闭包的方法
def paragraph puts "A good paragraph should have a topic sentence." yield puts "This generic paragraph has a topic, body, and conclusion." end paragraph {puts "This is the body of the paragraph."} Results: A good paragraph should have a topic sentence. This is the body of the paragraph. This generic paragraph has a topic, body, and conclusion. |
优点
通过将参数列表附加给 yield
,很容易利用定制闭包中的参数,如清单 7 中所示。
清单 7. 附加参数列表
def paragraph topic = "A good paragraph should have a topic sentence, a body, and a conclusion. " conclusion = "This generic paragraph has all three parts." puts topic yield(topic, conclusion) puts conclusion end t = "" c = "" paragraph do |topic, conclusion| puts "This is the body of the paragraph. " t = topic c = conclusion end puts "The topic sentence was: '#{t}'" puts "The conclusion was: '#{c}'" |
不过,请认真操作以保证得到正确的作用域。在闭包里声明的参数的作用域是局部的。例如,清单 7 中的代码可以运行,但清单 8 中的则不行,原因是 topic
和 conclusion
变量都是局部变量:
清单 8. 错误的作用域
def paragraph topic = "A good paragraph should have a topic sentence." conclusion = "This generic paragraph has a topic, body, and conclusion." puts topic yield(topic, conclusion) puts conclusion end my_topic = "" my_conclusion = "" paragraph do |topic, conclusion| # these are local in scope puts "This is the body of the paragraph. " my_typic = topic my_conclusion = conclusion end puts "The topic sentence was: '#{t}'" puts "The conclusion was: '#{c}'" |
闭包的应用
下面是一些常用的闭包应用:
当您可以用一种简单便利的方式构建自己的闭包时,您就找到了能带来更多新可能性的技术。重构能将可以运行的代码变成运行得更好的代码。大多数 Java 程序员都会从里到外 进行重构。他们常在方法或循环的上下文中寻找重复。有了闭包,您也可以从外到里 进行重构。
用闭包进行定制会有一些惊人之处。清单 9 是 Ruby on Rails 中的一个简短例子,清单中的闭包用于为一个 HTTP 请求编写响应代码。Rails 把一个传入请求传递给控制器,该控制器生成客户机想要的数据(从技术角度讲,控制器基于客户机在 HTTP accept
头上设置的内容来呈现结果)。如果您使用闭包的话,这个概念很好理解。
清单 9. 用闭包来呈现 HTTP 结果
@person = Person.find(id) respond_to do |wants| wants.html { render :action => @show } wants.xml { render :xml => @person.to_xml } end |
清单 9 中的代码很容易理解,您一眼就能看出这段代码是用来做什么的。如果发出请求的代码块是在请求 HTML,这段代码会执行第一个闭包;如果发出请求的代码块在请求 XML,这段代码会执行第二个闭包。您也能很容易地想象出实现的结果。wants
是一个 HTTP 请求包装程序。该代码有两个方法,即 xml
和 html
,每个都使用闭包。每个方法可以基于 accept
头的内容选择性地调用其闭包,如清单 10 所示:
清单 10. 请求的实现
def xml yield if self.accept_header == "text/xml" end def html yield if self.accept_header == "text/html" end |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者