科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道好处不止一点点 编程结构--闭包

好处不止一点点 编程结构--闭包

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

2007 年 1 月 22 日 闭包是可以用作函数参数和方法参数的代码块。一直以来,这种编程结构都是一些语言(如 Lisp、Smalltalk 和 Haskell)的重要组成部分。尽管一些颇具竞争力的语言(如 C

作者:中国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 中的则不行,原因是 topicconclusion 变量都是局部变量:



清单 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 请求包装程序。该代码有两个方法,即 xmlhtml,每个都使用闭包。每个方法可以基于 accept 头的内容选择性地调用其闭包,如清单 10 所示:



清单 10. 请求的实现

    
  def xml
    yield if self.accept_header == "text/xml"
  end
  def html
    yield if self.accept_header == "text/html"
  end
      

 

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章