函数式编程
面向对象编程OOP
解决问题
分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
对象:用户
行为:登录、JDBC、读取数据库
属性:用户名、密码
Scala语言是一个完全面向对象编程语言
对象的本质:对数据和行为的一个封装
函数式编程
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 [1]
和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
和过程化编程相比,函数式编程里函数的计算可随时调用。
函数基础
函数基本用法
def sum(x: Int, y: Int): Int = {
x + y
}
函数和方法的区别
为完成某一功能的程序语句的集合,成为函数
类中的函数称之为方法
函数定义
- 无参,无返回值
- 无参,有返回值
- 有参,无返回值
- 有参,有返回值
- 多参,无返回值
- 多参,有返回值
package chapter05
object Test02_FunctionDefine {
def main(args: Array[String]): Unit = {
// 无参,无返回值
def f1(): Unit = {
println("无参,无返回值")
}
f1()
println(f1())
println("-----------------------")
// 无参,有返回值
def f2(): String = {
println("无参,有返回值")
return "This is f2 return value."
}
// f2()
println(f2())
println("-----------------------")
// 有参,无返回值
def f3(name: String): Unit = {
println("有参,无返回值" + name)
}
println(f3("zihoo"))
println("-----------------------")
// 有参,有返回值
def f4(name: String): String = {
println("有参,有返回值" + name)
return "This is f4 return value"
}
println(f4("zihoo"))
println("-----------------------")
// 多参,无返回值
def f5(name1: String, name2: String): Unit = {
println("多参,无返回值")
println(name1 + "和" + name2 + "打招呼")
}
println(f5("zihoo", "gazikel"))
println("-----------------------")
// 多参,有返回值
def f6(a: Int, b: Int): Int = {
println("多参,有返回值")
return a + b
}
}
}
函数参数
- 可变参数
- 如果参数列表存在多个参数,那么可变参数一般放置在最后
- 参数默认值,一般将有默认值的参数防止在参数列表的后面
- 带名参数,带着参数名称传值,传值就可以与顺序无关
package chapter05
object Test03_FunctionParameter {
def main(args: Array[String]): Unit = {
// 可变参数
def f1(str: String*): Unit = {
println(str)
}
f1("zihoo")
f1("zihoo", "gazikel")
println("----------------------")
// 如果参数列表中存在多个参数,那么可变参数放在最后
def f2(number: Int, str: String*): Unit = {
println("number:" + number + ", str:" + str)
}
f2(10)
println("----------------------")
// 参数默认值,一般将有默认值的参数放置在参数列表的后面
def f3(name: String = "school"): Unit = {
println("I am at " + name)
}
f3()
f3("home")
println("----------------------")
// 带名参数
def f4(name: String, age: Int):Unit = {
println(s"${name}${age}岁了")
}
f4("zihoo", 21)
f4(age = 21, name = "zihoo")
}
}
函数至简原则
能省则省
package chapter05
object Test04_Simplify {
def main(args: Array[String]): Unit = {
def f0(name: String): String = {
return name
}
// return可以省略,Scala会使用函数体的最后一行代码作为返回值
def f1(name: String): String = {
name
}
// 如果函数体只有一行代码,可以省略花括号
def f2(name: String): String = name
// 返回值类型如果能够推断出来,那么可以省略
def f3(name: String) = name
// 如果有return,则不能省略返回值类型,必须指定
// 如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
def f5(name:String):Unit = {
return "这个return不起作用"
}
println(f5("zihoo"))
// Scala如果期望是无返回值类型,可以省略等号
def f6(name: String) {
println("可以省略等号")
}
// 如果函数无参,但是声明了参数列表,那么调用时,小括号可加可不加
def f7() = {
println("f7")
}
f7()
f7
// 如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f8 {
println("f8")
}
f8
// 如果不关心名称,只关心逻辑处理,那么可以将函数名省略
// 匿名函数,lambda表达式
(name: String) => { println(name) }
}
}
那么匿名函数连名字都没有,怎么调用呢?
下面,详细讲述一下lambda表达式的使用。
函数高级
高阶函数
函数可以作为值进行传递
package chapter05
object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
def f(n: Int): Int = {
println("f调用")
n + 1
}
val result = f(123)
println(result)
// 函数作为值进行传递
val f1: Int => Int = f
val f2 = f _
println(f1) // chapter05.Test06_HighOrderFunction$$$Lambda$5/1908923184@4563e9ab
println(f1(23))
println(f2) // chapter05.Test06_HighOrderFunction$$$Lambda$6/431687835@11531931
println(f2(35))
}
}
函数可以作为参数进行传递
package chapter05
object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
// 函数作为参数进行传递
// 定义二元计算函数
def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
op(a, b)
}
def add(num1: Int, num2: Int): Int = {
num1 + num2
}
println(dualEval(add, 1, 2))
dualEval((a, b) => {
a + b
}, 10, 20)
}
}
函数可以作为函数返回值返回
package chapter05
object Test06_HighOrderFunction {
def main(args: Array[String]): Unit = {
// 函数可以作为函数返回值返回
def f5(): Int => Unit = {
def f6(a: Int): Unit = {
println("f6调用" + a)
}
// 将函数直接返回
f6
}
println(f5()) // chapter05.Test06_HighOrderFunction$$$Lambda$9/1975358023@7d417077
f5()(26)
}
}
案例实操
对于集合的数据处理
package chapter05
object Test07_Practice_Collection {
def main(args: Array[String]): Unit = {
val arr: Array[Int] = Array(12, 45, 75, 98)
// 对数据进行处理,将操作抽象出来,处理完毕的结果返回一个新的数组
def arrayOperation(arr: Array[Int], op: Int=>Int): Array[Int] = {
for(elem <- arr) yield op(elem)
}
// 定义一个+1操作
def addOne(elem: Int): Int = {
elem + 1
}
// 调用函数
val newArray: Array[Int] = arrayOperation(arr, addOne)
println(newArray.mkString(","))
// 传入匿名函数
val newArray2: Array[Int] = arrayOperation(arr, (elem) => elem * 2)
println(newArray2.mkString(","))
}
}
匿名函数
没有名字的函数
高阶函数案例
-
定义一个匿名函数,并将它作为值赋给变量fun。函数有三个参数,类型分别为Int, String, Char,返回值类型为Boolean
要求调用函数
fun(0, "", '0')
得到返回值为false,其它情况均返回true -
定义一个函数func,它接收一个Int类型的参数,返回一个函数(记作f1)。它返回的函数f1,接收一个String类型的参数,同样返回一个函数(记作f2)。行距是f2接收一个Char类型的参数,返回一个Boolean值。
要求调用函数
func(0)("")('0')
得到返回值为false,其它情况均返回true
package chapter05
object Test08_Practice {
def main(args: Array[String]): Unit = {
// 练习1
val fun = (i: Int, s: String, c: Char) => {
if (i == 0 && s == "" && c =='0') {
false
} else {
true
}
}
println(fun(0, "", '0'))
println(fun(1, "", '0'))
def func(i: Int): String => Char => Boolean = {
def f1(str: String): Char => Boolean = {
def f2(c: Char): Boolean = {
if (i == 0 && str == "" && c =='0') {
false
} else {
true
}
}
f2
}
f1
}
}
}
函数柯里化&闭包
闭包:如果一个函数,访问到了它的内部(局部)变量的值,那么这个函数和它所处的环境,称为闭包。
函数柯里化:把一个参数列表的多个参数,编程多个参数列表。
递归
一个函数(或方法)在函数(方法)体内又调用了本身,我们称之为递归调用。
package chapter05
object Test10_Recursion {
def main(args: Array[String]): Unit = {
println(fact(5))
}
// 递归实现计算阶乘
def fact(n: Int): Int = {
if(n==1)
1
else
(n - 1) * n
}
}
控制抽象
值调用:把计算后的值传递过去
package chapter05
object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {
// 传值参数
def f0(a: Int): Unit = {
println("a:" + a)
}
f0(23)
def f1(): Int = {
println("f1调用")
12
}
f0(f1())
}
}
名调用:把代码传递过去
package chapter05
object Test11_ControlAbstraction {
def main(args: Array[String]): Unit = {
def f1(): Int = {
println("f1调用")
12
}
f0(f1())
println("-------------")
// 传名参数
def f2(a: => Int): Unit = {
println("a:" + a)
println("a:" + a)
}
f2(f1())
f2({
println("这是一个代码块")
29
})
}
}
惰性函数
当函数返回值被声明为lazy时,函数的执行被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
package chapter05
object Test13_Lazy {
def main(args: Array[String]): Unit = {
lazy val result: Int = sum(13, 47)
println("1. 函数调用")
println("2. result = " + result)
def sum(a: Int, b: Int): Int = {
println("3. sum调用")
a + b
}
}
}