Scala 方法和函数
方法与函数
Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
Scala 中使用 val 语句可以定义函数,def 语句定义方法。
方法定义
方法定义由一个 def 关键字开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。
定义格式如下:
1 | def functionName ([参数列表]) : [return type] = { |
以上代码中 return type 可以是任意合法的 Scala 数据类型。参数列表中的参数可以使用逗号分隔。
以下方法的功能是将两个传入的参数相加并求和:
1 | object add{ |
函数
Scala 也是一种函数式语言,所以函数是 Scala 语言的核心。以下一些函数概念有助于我们更好的理解 Scala 编程,定义方式上,和scala方法是一样的。
传值函数&传名函数
**
Scala的解释器在解析函数参数(function arguments)时有两种方式:先计算参数表达式的值(reduce the arguments),再应用到函数内部;或者是将未计算的参数表达式直接应用到函数内部。前者叫做传值调用(call-by-value),后者叫做传名调用(call-by-name)
1 | object Test { |
注:scala函数体和方法体中的最后一行为返回值
结果:
1 | 在 delayed 方法内 |
=> Unit 与 () =>Unit的区别
简单来说, => Unit是 传名函数, 只传入了一个表达式, 在调用时才会去执行, 使用 code调用
() => 是传值函数, 传入的计算后的值,示例例如:
1 | def function_1(t: () => Long): Unit = { |
指定函数参数名
**
不管在用什么语言在进行开发的过程中,对于函数的传参,我们几乎都是按照函数定义中,参数的顺序进行传参的,但是在Scala中会灵活一些,我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参数,实例如下:
1 | object Test { |
可变参数
**
Scala 允许你指明函数的最后一个参数可以是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。例如:
1 | object Test { |
**递归函数**
1 | object Test { |
默认参数值
Scala 可以为函数参数指定默认参数值,使用了默认参数,你在调用函数的过程中可以不需要传递参数,这时函数就会调用它的默认参数值,如果传递了参数,则传递值会取代默认值。实例如下:
1 | object Test { |
高阶函数
高阶函数(Higher-Order Function)就是操作其他函数的函数。
Scala 中允许使用高阶函数, 高阶函数可以使用其他函数作为参数,或者使用函数作为输出结果。
以下实例中,apply() 函数使用了另外一个函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v:**
1 | object Test { |
匿名函数
**
匿名函数的语法很简单,箭头左边是参数列表,右边是函数体。使用匿名函数后,我们的代码变得更简洁了。
下面的表达式就定义了一个接受一个Int类型输入参数的匿名函数:
1 | var inc = (x:Int) => x+1 |
上述定义的匿名函数,其实是下面这种写法的简写:
1 | def add2 = new Function1[Int,Int]{ |
以上实例的 inc 现在可作为一个函数,使用方式如下:
1 | var x = inc(7)-1 |
同样我们可以在匿名函数中定义多个参数:
1 | var mul = (x: Int, y: Int) => x*y |
mul 现在可作为一个函数,使用方式如下:
1 | println(mul(3, 4)) |
我们也可以不给匿名函数设置参数,如下所示:
1 | var userDir = () => { System.getProperty("user.dir") } |
userDir 现在可作为一个函数,使用方式如下:
1 | println( userDir() ) |
偏应用函数
偏应用函数也是一个蛮有意思的用法,**Scala 偏应用函数是一种表达式,你不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
1 | import java.util.Date |
执行以上代码,输出结果为:
1 | $ scalac Test.scala |
实例中,log() 方法接收两个参数:date 和 message。我们在程序执行时调用了三次,参数 date 值都相同,message 不同。
我们可以使用偏应用函数优化以上方法,绑定第一个 date 参数,第二个参数使用下划线(_)替换缺失的参数列表,并把这个新的函数值的索引的赋给变量。以上实例修改如下:
1 | import java.util.Date |
执行以上代码,输出结果为和上面的是一样的。