Kotlin使用lambda 表达式促成
可以在变量与数据结构中存储函数
可以作为参数传递给其他高阶函数
可以从其他高阶函数返回
可以像操作任何其他非函数值一样对函数进行操作
将函数用作参数或返回值的函数,即高阶函数
高阶函数定义,只需要将参数类型或返回值类型中的任意一个定义为函数类型即可
// 参数类型是函数类型
修饰符 函数名(参数名:(T...)-> R) : 返回值类型 {
...
方法体
...
return 返回值;
}
// 返回值类型是函数类型
修饰符 函数名(参数名:参数类型) : (T...)-> R {
...
方法体
...
return 返回值;
}
格式: (T...)->
R (T、R均表示泛型) T...表示可以有多个形参,R也可以是Unit
分类:
() ->
R, 表示无参,返回R类型的函数
// () -> R 类型函数声明和定义
//lamba形式
val aaa : () -> Int = {444}
val bbb : () -> Unit = {println("Unit")}
// 调用函数
println(aaa()) // 444
bbb() // Uint
// 函数形式
fun fun1(n: Int, lamba: () -> Int) : Unit {
println("$n")
println("${lamba()}")
}
// 调用函数
fun1(111, aaa)
/*
111
444
*/
(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)
/*
222
word
444.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 444
555
*/
// 函数形式
fun fun1(n: Int, lamba: String.(Int) -> Int) : Unit {
println("$n")
println("${lamba("word", 234)}")
}
// 调用函数
fun1(111, aaa)
/*
111
word 234
555
*/
->
R),表示接收输入一个T参数和一个代码块参数的函数 //接收(T, T.() -> R) 参数类型的函数声明和定义
val aaa: (f: Float, s: String.(Int) -> Float) -> Int = {f, s ->
println("$f") // 444.0
var bb = s("hello", 444)
println("$bb") // hello, 444
555
}
// 调用函数
var cc = aaa(444.0f){
println("$this, $it") // 333.0
333.0f
}
println("$cc") // 555
// 函数形式
fun fun1(f: Float, s: String.(Int) -> Float) : Int {
println("$f") // 111.0
var dd = s("word", 234)
println("$dd") // 222.0
return 123
}
// 调用函数
val ee = fun1(111f) {
println("$this $it") // word 234
222.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 表达式是函数字面值,即没有声明而是立即做为表达式传递的函数
语法:
->
之后。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 > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
下划线:_ 接收变量
// 参数1不使用,那么可以用下划线(_)取代其名称
map.forEach { (_, value) -> println("$value!") }
像常规函数一样声明,但省略其名称;当匿名函数作为参数传递时,需将其放在括号内;允许将函数留在圆括号外的简写语法仅适用于 lambda 表达式
// lamba 形式
fun(x: Int, y: Int): Int = x + y
// 函数形式
fun(x: Int, y: Int): Int {
return x + y
}