Kotlin使用lambda 表达式促成
可以在变量与数据结构中存储函数
可以作为参数传递给其他高阶函数
可以从其他高阶函数返回
可以像操作任何其他非函数值一样对函数进行操作
1、高阶函数
将函数用作参数或返回值的函数,即高阶函数
高阶函数定义,只需要将参数类型或返回值类型中的任意一个定义为函数类型即可
// 参数类型是函数类型修饰符 函数名(参数名:(T...)->R) : 返回值类型 {...方法体...return 返回值;}// 返回值类型是函数类型修饰符 函数名(参数名:参数类型) : (T...)->R {...方法体...return 返回值;}
2、函数类型
格式: (T…)->
R(T、R均表示泛型) T…表示可以有多个形参,R也可以是Unit
分类:
()
->
R,表示无参,返回R类型的函数
// () ->R 类型函数声明和定义//lamba形式val aaa : () -> Int = {444}val bbb : () -> Unit = {println("Unit")}// 调用函数println(aaa()) //444bbb()//Uint// 函数形式fun fun1(n: Int, lamba: () -> Int) : Unit {println("$n")println("${lamba()}")}// 调用函数fun1(111, aaa)/*111444*/
(T)
->
R, 表示一个T类型参数,返回R类型的函数
// (T) ->R 类型函数声明和定义val aaa : (String) -> Float = {println("$it")444.0f}// 调用函数println(aaa("hello")) /* hello 444.0*/// 函数形式fun fun1(n: Int, lamba: (String) -> Float) : Unit {println("$n")println("${lamba("word")}")}// 调用函数fun1(111, aaa)/*222word444.0*/
T.(A)
->
R, 表示在T
的接收者对象上用一个 A类型参数来调用,返回一个R类型值的函数
// T.(A) ->R 类型函数声明和定义val aaa: String.(Int) -> Int = {// 传给调用的接收者对象成为隐式的this,// 以便访问接收者对象的成员而无需任何额外的限定符,// 亦可使用 this 表达式 访问接收者对象println("$this $it")555}// 调用函数println(aaa("hello", 444)) /*hello 444555*/// 函数形式fun fun1(n: Int, lamba: String.(Int) -> Int) : Unit {println("$n")println("${lamba("word", 234)}")}// 调用函数fun1(111, aaa)/*111word 234555*/
- (T,T.()
->
R),表示接收输入一个T参数和一个代码块参数的函数
//接收(T,T.() -> R) 参数类型的函数声明和定义val aaa: (f: Float, s: String.(Int) -> Float) -> Int = {f, s ->println("$f")// 444.0var bb = s("hello", 444)println("$bb") // hello, 444555}// 调用函数var cc = aaa(444.0f){println("$this, $it")// 333.0333.0f}println("$cc") // 555// 函数形式fun fun1(f: Float, s: String.(Int) -> Float) : Int {println("$f")// 111.0var dd = s("word", 234)println("$dd") // 222.0return 123}// 调用函数val ee = fun1(111f) {println("$this $it") // word 234222.0f}println("$ee") // 123
函数的参数名可选:(x: Int, y: Int) -> Point
;若返回Unit 类型不可省略,表示无返回值
使用圆括号,将函数类型指定为可空:((Int, Int) -> Int)?
使用圆括号,进行接合:(Int) -> ((Int) -> Unit)
箭头表示法是右结合的:(Int) -> (Int) -> Unit
与前述示例等价,但不等于((Int) -> (Int)) -> Unit
class A// 下面两个函数的调用方式都一样,都需要传入一个A对象,不同之处在函数体内val myFun1 = fun A.() { // 在函数体内隐含this,可直接调用T成员变量和函数 }val myFun2 = fun(a: A) { // 普通函数,必须使用a.的方式显式调用A类内的任意函数和变量 }
3、
Lambda 表达式
lambda 表达式是函数字面值,即没有声明而是立即做为表达式传递的函数
语法:
- lambda 表达式总是括在花括号中
- 完整语法形式的参数声明放在花括号内,并有可选的类型标注
- 函数体跟在一个
->
之后。 - 返回类型如果推断不是
Unit
,则以 { } 里最后一个(或可能是单个)表达式会视为返回值
// 完整形式val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }// 简写形式val sum = { x: Int, y: Int -> x + y }
拖尾 lambda 表达式:
// 按照 Kotlin 惯例,如果函数的最后一个参数是函数// 那么作为相应参数传入的 lambda 表达式可以放在圆括号之外val product = items.fold(1) { acc, e -> acc * e }// 如果该 lambda 表达式是调用时唯一的参数,那么圆括号可以完全省略run { println("...") }
单个参数的隐式名称:it
// 字面值是“(it: Int) -> Boolean”类型的val aaa = { it > 0 }
限定返回语法:return@xxx 从 lambda 显式返回一个值,否则,将隐式返回最后一个表达式的值
// 两个返回值是一样的ints.filter {val shouldFilter = it > 0shouldFilter}ints.filter {val shouldFilter = it > 0return@filter shouldFilter}
下划线:_ 接收变量
// 参数1不使用,那么可以用下划线(_)取代其名称map.forEach { (_, value) -> println("$value!") }
4、匿名函数
像常规函数一样声明,但省略其名称;当匿名函数作为参数传递时,需将其放在括号内;允许将函数留在圆括号外的简写语法仅适用于 lambda 表达式
// lamba 形式fun(x: Int, y: Int): Int = x + y// 函数形式fun(x: Int, y: Int): Int {return x + y}