减少Scala中的代码重复

发表于:2011-9-01 09:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Martin Odersky等    来源:51Testing软件测试网采编

分享:

  这个例子中展示的函数文本使用了前一章中介绍的占位符语法,对你来说可能感觉不是非常自然。因此,以下阐明例子里是如何使用占位符的。用在filesEnding方法里的函数文本_.endsWith(_),与下面的是一回事:

(fileName: String, query: String) => fileName.endsWith(query)

  原因是filesMatching带一个函数,这个函数需要两个String参数,不过你不需要指定参数类型。因此,你也可以写成(fileName, query) => fileName.endsWith(query)。由于第一个参数,fileName,在方法体中被第一个使用,第二个参数,query,第二个使用,你也可以使用占位符语法:_.endsWith(_)。第一个下划线是第一个参数,文件名的占位符,第二个下划线是第二个参数,查询字串的占位符。

  代码已经被简化了,但它实际还能更短。注意到query传递给了filesMatching,但filesMatching没有用查询做任何事只是把它传回给传入的matcher函数。这个传来传去的过程不是必需的,因为调用者在前面就已经知道了query的内容。你可以同样从filesMatching和matcher中简单地去除query参数,因此简化后的代码如展示在代码9.1中那样。

  • object FileMatcher {  
  •  private def filesHere = (new java.io.File(".")).listFiles  
  •  private def filesMatching(matcher: String => Boolean) =  
  •   for (file < - filesHere; if matcher(file.getName))  
  •    yield file  
  •  def filesEnding(query: String) =  
  •   filesMatching(_.endsWith(query))  
  •  def filesContaining(query: String) =  
  •   filesMatching(_.contains(query))  
  •  def filesRegex(query: String) =  
  •   filesMatching(_.matches(query))  
  • }
  •   这个例子演示了函数作为第一类值帮助你减少代码重复的方式,如果没有它们这将变得很困难。比方说在Java里,你可以创建包括带一个String并返回Boolean的方法的接口,然后创建并传递实现这个接口的匿名内部类实例给filesMatching。尽管这个方式能去除你尝试简化掉的代码重复,但同时它增加了许多乃至更多的新代码。因此好处就不值这个开销了,于是你或许就安于重复代码的现状了。

      再者,这个例子还演示了闭包是如何能帮助你减少代码重复的。前面一个例子里用到的函数文本,如_.endsWith(_)和_.contains(_),都是在运行期实例化成函数值而不是闭包,因为它们没有捕获任何自由变量。举例来说表达式_.endsWith(_)里用的两个变量,都是用下划线代表的,也就是说它们都是从传递给函数的参数获得的。因此,_.endsWith(_)使用了两个绑定变量,而不是自由变量。相对的,最近的例子里面用到的函数文本_.endsWith(query),包含一个绑定变量,下划线代表的参数,和一个名为query的自由变量。仅仅因为Scala支持闭包才使得你可以在最近的这个例子里从filesMatching中去掉query参数,从而更进一步简化了代码。

    22/2<12
    《2023软件测试行业现状调查报告》独家发布~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号