函数式编程
方法
-
对象:
封装数据
-
方法:步骤的封装
方法定义方式:
def 方法名(参数名:参数类型,…………):返回值类型={
方法体
}
-
方法的简化
- 方法体中的语句只有一句可以省略{},类似Java中的if省略一句的情况
- 由于存在自动类型推断,可以省略方法中的返回值(但最后一句必须是可以作为返回值的表达式或结果值)
- 如果方法体中有return,必须确定返回值类型
- 如果方法不需要参数,那么在方法定义时可以省略参数列表的()
- 省略()后,调用该方法时,不能带上()
- 没省略()时,调用该方法时,可以带上(),也可以不带()
- 方法不需要返回值时,可以在定义方法时,省略=
- 需注意的是,=和{}不能同时省略
-
方法的参数
- 默认值参数:定义方法时,对参数默认值进行了赋值。在调用时,可以不对参数赋值(即使用默认值)
- 带名参数:结合默认参数,在调用方法时,对特定参数进行了新的赋值(带名带的是定义方法时的参数名)
- 可变参数:类似Java中的可变形参,参数的个数不固定
- 语法:def 方法名(参数名:类型,……,参数:类型*):返回值类型={}
- 注意:
- 可变参数不能与默认值参数一起使用
- 可变参数必须在形参列表的末尾
- 可变参数不能直接传递数组,想要传递一个集合给可变参数,需要通过 集合名:_* 的方式传递
- 可变参数必须在形参列表的末尾
- 可变参数不能与默认值参数一起使用
函数
-
函数的定义
- val 函数名 = (参数名:类型,...) => { 函数体 }
- 函数的返回值默认就是函数体块表达式的结果值
- 函数是对象,
- 函数的类型: (参数类型,...) => 返回值类型
- val 变量名:变量类型 = 变量值
-
函数的简化
- 如果函数体的{}中只有一个语句,{}可以省略
方法和函数
- 区别
- 方法如果定义在class/Object中都可以重载,函数是对象,故函数不可以重载
- 方法存储在方法区中;函数是对象,对象是存储在堆中
- 联系
- 方法如果定义在方法中,此时方法就是函数,不能进行重载
- 比如定义一个方法A在main方法中,此时方法A就是一个函数
- 手动将方法转换为函数:方法名 _ (下划线前有空格)
- 方法如果定义在方法中,此时方法就是函数,不能进行重载
高阶函数
-
定义
以函数作为参数/函数/返回值的方法
-
简化(调用高阶函数时才能简化)
- 直接传递函数的值
- 函数的参数类型可以省略
- 如果函数的参数在函数体中只使用了一次,那么可以使用占位符_代替
- 以下几种情况不能使用占位符
- 如果函数的参数使用顺序与定义顺序不一致,此时不能使用下划线简化【第几个下划线就代表第几个参数】《只针对有多个参数的情况》
- 如果函数体中有嵌套,函数的参数在嵌套中以表达式的形式存在,此时不能使用下划线简化《针对函数体中有嵌套的情况》
- 如果函数只有一个参数,在函数体中没有进行任何操作直接返回参数时,此时也不能使用下划线简化《针对函数只有一个参数的情况》
- 以下几种情况不能使用占位符
- 如果函数只有一个参数,那么函数的参数列表()可以省略
匿名函数
-
定义:
- 没有函数名的函数,常用于给高阶函数传参
-
声明方式
- 就是高阶函数中缩略了函数名的函数。
函数柯里化
-
说明
- 将一个接收多个参数的函数转化成一个接受一个参数的函数过程,可以简单的理解为一种特殊的参数列表声明方式。
-
算式推导
//目标式 def add( x:Int,y:Int )(z:Int)(a:Int) = x+y+z+a /** * 柯里化演变过程 */ def m1(x:Int,y:Int) = { val func = (z:Int) => { val f1 = (a:Int) => { x+y+z+a } f1 } func }
闭包
-
定义
- 函数体中使用了不属于函数本身的变量的情况称之为闭包。即:一个函数和与其相关的引用环境(变量)组合的一个整体(实体)
//外部变量
var z: Int = 10
//闭包
def f(y: Int): Int = {
z + y
}
递归
定义
- 一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
条件
- 有退出
- 必须定义返回值类型
- 函数的递归不能写在方法内部(因为函数是一个对象,需要创建了才能使用)
惰性求值
-
语法:lazy val 变量名 = 值
def main(args: Array[String]): Unit = { lazy val res = sum(10, 30) println("----------------") println("res=" + res) } val sum =(n1: Int, n2: Int)=> { println("sum被执行。。。") return n1 + n2 } 结果: ---------------- sum被执行。。。 res=40
-
注意:lazy标识的变量只有在使用的时候才会初始化,没有使用之前不会初始化。(类似Java中的懒汉式设计模式)需要注意的是,惰性求值只适用于函数上,当然方法也可以转换为函数。
控制抽象
- 语法: =>返回值类型
- 注意:
- 控制抽象不能单独使用,只能作为方法的参数存在
- 控制抽象其实就是一个<块表达式>,控制抽象中返回值类型就是<块表达式>的结果值类型,后续看到方法的参数类型是控制抽象的时候,其实就是让你传一个块表达式。
- 控制抽象可以当做函数调用,调用的时候不能带上(),否则调用一次,控制抽象的块表达式就执行一次