一. 基础
1. 介绍
- 在scala中,方法和函数几乎可以等同(比如他们的定义、使用、运行机制都一样的),只是函数的使用方式更加的灵活多样 [方法转函数]。
- 函数式编程是从编程方式(范式)的角度来谈的,可以这样理解:函数式编程把函数当做一等公民,充分利用函数、 支持的函数的多种使用方式。比如:
在Scala当中,函数是一等公民,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量. 函数的创建不用依赖于类或者对象,
而在Java当中,函数的创建则要依赖于类、抽象类或者接口. - 面向对象编程是以对象为基础的编程方式。
- 在scala中函数式编程和面向对象编程融合在一起了 。
2. 函数/方法的定义
1. 基本语法
-
def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] { 语句... //完成某个功能 return 返回值 }
2. 说明
- 函数声明关键字为def (definition)
- [参数名: 参数类型], …:表示函数的输入(就是参数列表), 可以没有。 如果有,多个参数使用逗号间隔
- 函数中的语句:表示为了实现某一功能代码块
函数可以有返回值,也可以没有 - 返回值形式
- 形式1 // def 函数名(参数列表) : 数据类型 = {函数体} // 返回值确定,清晰
- 形式2: // def 函数名(参数列表) = {函数体} // 有返回值, 类型是推断出来的
- 形式3: // def 函数名(参数列表) {函数体} // 无返回值 Unit
- 如果没有return ,默认以执行到最后一行的结果作为返回值
3. 函数/方法注意事项和细节讨论
- 函数的形参列表可以是多个, 如果函数没有形参,调用时, 可以不带()
- 形参列表和返回值的数据类型可以是值类型和引用类型。
- Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return关键字可以省略
- 因为Scala可以自行推断,所以在省略return关键字的场合,返回值类型也可以省略
- 如果函数明确使用return关键字,那么函数返回就不能使用自行推断了,这时要明确写成 : 返回类型 = ,当然如果你什么都不写,即使有return 返回值为()
- 如果函数明确声明无返回值(声明Unit),那么函数体中即使使用return关键字也不会有返回值
- 如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为Any)
- Scala语法中任何的语法结构都可以嵌套其他语法结构(灵活),即:函数/方法中可以再声明/定义函数/方法,类中可以再声明类。
- 递归函数未执行之前是无法推断出来结果类型,在使用时必须有明确的返回值类型
3. 函数/方法的参数
1. 有默认值的参数
-
Scala函数的形参,在声明参数时,直接赋初始值(默认值),这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值
-
如果存在多个参数,默认按照声明顺序[从左到右]覆盖默认值. 也可以采用带参数的方式覆盖指定的参数
object Test06 { def fun1(a: String, b: String = "hello"): String = { s"a = $a, b = $b" } def main(args: Array[String]): Unit = { val str1: String = fun1("AAA") println(str1) val str2: String = fun1("AAA", "BBB") println(str2) val str3: String = fun1(b = "AAA", a = "BBB") println(str3) } }
2. 可变参数
-
代码
object Test06 { def fun1(a: String, b: Int*): String = { var sum = 0 for (ele <- b.tail) { sum += ele } sum + b.head + a } def main(args: Array[String]): Unit = { val str1: String = fun1("AAA", 1) println(str1) val str2: String = fun1("BBB", 2, 3) println(str2) } }
4. 匿名函数
-
案例1:
val f1 = () => "abc" println(f1) println(f1()) println(f1.apply())
-
案例2:
val f2: (String, Int) => Int = (str: String, num: Int) => str.toInt + num println(f2("5", 7)) val f3 = (str: String, num: Int) => str.toInt + num println(f3("5", 7)) val f4: (String, Int) => Int = (str, num) => str.toInt + num println(f4("5", 7))
4. 高阶函数
函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型是函数的函数。
1. 函数的参数是函数
-
代码
object Test08 { def fun1(f: (Int, Int) => Int, a: Int): Int = { f(a, 20) } def f(v1: Int, v2: Int): Int = { v1 + v2 } def main(args: Array[String]): Unit = { println(fun1(f, 10)) // 30 } }
2. 函数的返回值是函数
-
代码
object Test08 { def fun2(a: Int, b: Int): (Int, Int) => Int = { def f(v1: Int, v2: Int): Int = { v1 + v2 + a + b } f } def main(args: Array[String]): Unit = { println(fun2(10, 20)(30, 40)) } }
3. 函数的参数和返回值都是函数
-
代码
object Test08 { def fun3(f: (Int, Int) => Int): (Int, Int) => Int = { f } def f(a: Int, b: Int): Int = { a + b } def main(args: Array[String]): Unit = { println(fun3(f)(10, 20)) println(fun3((a, b) => a + b)(10, 20)) println(fun3(_ + _)(10, 20)) } }
5. 柯里化函数
柯里化指的是将原来接受多个参数的函数变成新的接受一个参数的函数的过程, 新函数的参数接受原来的第二个参数为唯一参数, 如果有n个参数, 就是把这个函数分解成n个新函数的过程
1. 说明
- 函数编程中,接受多个参数的函数都可以转化为接受单个参数的函数,这个转化过程就叫柯里化
- 柯里化就是证明了函数只需要一个参数而已。
- 柯里化就是以函数为主体这种思想发展的必然产生的结果。(即:柯里化是面向函数思想的必然产生结果)
2. 案例
def func(a: Int, b: Int)( c: Int, d: Int): Int = {
a + b + c + d
}
println(func(1, 2)(3, 4))
声明:
- 本文参考了尚硅谷Scala课程的课件