Scala编程(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

8.2 局部函数

前一节的processFile方法的构建展示了函数式编程风格的一个重要设计原则:程序应该被分解成许多小函数,每个函数都只做明确定义的任务。单个函数通常都很小。这种风格的好处是可以让程序员灵活地将许多构建单元组装起来,完成更复杂的任务。每个构建单元都应该足够简单,简单到能够单独理解的程度。

这种方式的一个问题是助手函数的名称会污染整个程序的命名空间。在解释器中,这并不是太大的问题,不过一旦函数被打包进可复用的类和对象当中,我们通常都希望类的使用者不要直接看到这些函数。它们离开了类和对象单独存在时通常都没有什么意义,而且通常你都希望在后续采用其他方式重写该类时,保留删除助手函数的灵活性。

在Java中,帮助你达到此目的的主要工具是私有方法。这种私有方法的方式在Scala中同样有效,如示例8.1所示,不过Scala还提供了另一种思路:可以在某个函数内部定义函数。就像局部变量一样,这样的局部函数只在包含它的代码块中可见。例如:

在本例中,我们对示例8.1原先的LongLines做了重构,将私有方法processLine转换成了一个局部函数。为此我们移除了private修饰符(这个修饰符只能也只需要加在成员上),并将processLine的定义放在了processFile的定义中。作为局部函数,processLineprocessFile内有效,但不能从外部访问。

既然现在processLine定义在processFile内部,我们还可以做另一项改进。注意到filenamewidth被直接透传给助手函数,完全没有变吗?这里的传递不是必需的,因为局部函数可以访问包含它们的函数的参数。可以直接使用外部的processFile函数的参数,如示例8.2所示:

示例8.2 带有局部processLine函数的LongLines

这样更简单,不是吗?使用外层函数的参数是Scala提供的通用嵌套机制的常见而有用的示例。7.7节介绍的嵌套和作用域对Scala所有语法结构都适用,函数当然也不例外。这是个简单的原理,但非常强大,这一点在支持一等函数(first-class function)的编程语言中尤为突出。