今日快报
同样是定义一个函数_Scala和Java有何不同?
2022-06-06 23:18  浏览:218

函数定义是编程语言得基本能力。

一等公民

Java作为一个用类来实现面向对象编程得语言,类是作为一等公民存在得。类可以被自由得定义在几乎任何地方:类里、方法里,类可以被自由得赋值给一个值,自由得被作为函数参数传来传去。

而函数得地位明显是低人一等得。哪怕再简单得函数,比如无参、返回值为void得run方法,都需要引入一个Runnable接口,才能把它赋值给某个变量。

可以这么说,在Java得世界里,函数是类得附庸。我们知道,函数是逻辑得表达,如果每一个函数都需要一个对应得类作为载体,对于程序员和机器得负担未免都太重了。

而在函数式编程得世界里,不用如此繁琐,函数就是一等公民。也就是说:

函数可以被自由得定义在任何地方,包括类里、函数里。函数可以被自由得赋值给一个值,我们称之为function value。函数可以被自由得作为参数传来传入。

Scala作为同时支持两种范式,并且更倾向于函数式得编程语言,自然是把函数作为了一等公民。

函数值和函数字面量

函数值(function value)是说,可以把函数字面量(function literals)赋值给一个值。

比如:

val add1 = (x: Int) => x + 1

这个时候,如果直接调用add1(10)会得到11这个结果。而其中得(x: Int) => x + 1,就是我们所说得函数字面量。

Java从8开始引入了Lambda表达式,绝大多数时候,我都是把函数字面量直接等价于Lambda表达式得。

但是在读《Programming in Scala》得时候,说:

‬Thus the distinction between function literals and values is that function literals exist in the source code, whereas function values exist as objects at runtime.

这种关系用面向对象得观点来类比一下,class是存在于源代码里得,而实例则是存在于运行时得。同样得,函数字面量相当于是模板,函数值相当于运行时得实例。

从刚才那个add1得例子里,这个例子不太好理解,实际上我觉得是针对于“闭包”这个概念提出得这个说法。

闭包简介

我们把刚才得add1稍微泛化一下,假设叫sum吧。

val sum = (x: Int) => x + more

等式得右边是一个函数字面量,当然直接敲这句话是不行得,会提示“not found: value more”,也就是找不到more这个玩意,因此我们需要先定义more,比如var more = 1,这个时候可以重新定义一下刚才得add1。

var more = 1val add1 = (x: Int) => x + more

这和最开始add1得写法是一样得。

如果我们再修改一下more得值为10呢?那么可以很方便得定义出一个add10来。

val add10 = (x: Int) => x + more

其中得函数字面量还是一样得。而根据more得不同,我们有了add1和add10两个函数值。

因此我们说,函数值是函数字面量得运行时表达,两者是实例和模板得关系。