5.3 函数式编程和命令式编程
从本质上说,Java是一种命令式编程语言。在命令式编程语言中,变量通常是可修改的,而类通常保存了内部状态。在Java中,POJO(Plain Old Java Object)是命令式编程的典范。标准POJO包含可通过调用设置方法随便修改的变量,可访问POJO实例的任何代码都可修改其变量。这可能导致难以发现的微妙bug,多个线程试图同时修改同一个变量时尤其如此。
在函数式编程中是这样编写代码的,即确保在程序运行期间不会修改任何既有的变量。值是以函数参数的方式指定的,而输出是根据参数生成的。每次调用函数时,只要指定的参数相同,输出就必须相同。
下面来看一个非常简单的示例。请不要过多地关注其中的语法,因为本章后面将详尽地介绍Scala语言的语法。先来看一个传统的Scala面向对象编程示例:
class AddDemoOOP {var x = 0def add(y: Int): Int = {x += yx}}val a = new AddDemoOOP()print(a.add(1))print(a.add(1))
这将打印1和2。虽然两次调用时方法add接受的参数相同(都是整数1),但它们返回的值不同。这是因为这个方法修改了类的状态。在纯粹的函数式编程中,这是不允许的。下面是这个类的函数式版本:
class AddDemoFunctional {def add(x: Int, y: Int): Int = {x + y}}val b = new AddDemoFunctionalprint(b.add(0, 1))print(b.add(0, 1))
这将打印1两次。这个版本的类没有存储任何内部状态。要让方法add返回不同的值,必须给它传递不同的参数。
注意,Scala虽然是纯粹的OOP语言,但并不是纯粹的函数式编程语言。如第一个示例所示,使用Scala很容易编写不遵循函数式编程规则的代码。
编写使用多个线程的程序时,函数式编程是一种流行的选择。由于方法不能修改在多个线程中使用的数据结构的状态,因此函数式编程通常比命令式编程安全得多,但这要求开发人员使用不同的思维方式。
有关函数式编程可说的还有很多,本章后面将介绍其他一些与此相关的主题。
不同于众多其他的函数式编程语言,Scala让你能够按自己的步伐学习函数式编程,因为它是纯粹的面向对象编程语言。
注意,Scala虽然是纯粹的OOP语言,但并不是纯粹的函数式编程语言。如第一个示例所示,使用Scala很容易编写不遵循函数式编程规则的代码。