在Kotlin编程中,lambda表达式的应用非常常见,这篇文章用来介绍一下怎样用lambda表达式定义函数,用lambda表达式进行函数传参,以及简化lambda表达式
参考文档: https://developer.android.com
用lambda表达式定义函数
先来看一个最简单的例子:
val trick={
println("No treats!")
}
关键点:
1.lambda表达式的结果是一个值,因此可以直接将其存储在变量中(即上图中的trick中)
2."="后面即为lambda表达式,大括号中的内容为函数正文
怎样调用
fun main(){
val trickFunction=trick//kotlin的推导机制可以判断出trick为函数类型
trick()
trickFunction()
}
加上参数和返回值
刚才的trick函数非常简单,它的数据类型为()->Unit,()为空,代表它不接受任何参数,返回值类型为Unit,代表它不返回任何内容,所以它较为完整的写法是这样的
val treat:()->Unit={
println("Have a treat!")
}
那么现在来看一个复杂的函数
val trick={
println("No treats!")
}
fun trickOrTreat(isTrick:Boolean):()->Unit{
if(isTrick){
return trick
}else{
return treat
}
}
首先,我们又用lambda表达式定义了一个简单的函数trick,在trickOrTreat()函数的正文中,设置一个if语句,使其在 isTrick
为 true
时返回 trick()
函数,并在 isTrick
为 false 时返回 treat()
函数。
代码逻辑理好了,现在来测试一下:
fun main(){
val treatFunction=trickOrTreat(false)
val trickFunction=trickOrTreat(true)
treatFunction()
trcikFunction()
}
输出结果如下:
Have a treat!
No treats!
在刚才的trickOrtreat
函数中,我们将函数作为返回值,那么该怎样将函数作为参数传递呢?
举个栗子:
fun trickOrTreat(isTrick:Boolean,extraTreat:(Int)->String):()->Unit{
if(isTrick){
return trick
}else{
println(extraTreat(5))
return treat
}
}
在这个函数中,添加了类型为(Int)->String
的extraTreat函数参数,这代表trickOrTreat
函数接受一个函数作为参数,其参数类型为Int
返回值类型为String
那么现在我们来编写两个这样的函数来进行测试
fun main(){
val coins:(Int)->String={
quantity->"$quantity auarters"
}//quantity为Int参数(可省略),lambda表达式不支持return语句,函数中最后一个表达式的结果将成为返回值,详情下回分解
val cupcake:(Int)->String={
quantity->"Have a cupcake!"
}
val treatFunction = trickOrTreat(false,coins)
val trickFunction = trickOrTreat(true,cupcake)
treatFunction()
trickFunction()
}
在main
函数中,我们定义了两个以Int类型为参数,返回值为String的函数,并将其作为参数传入到trickOrTreat
函数中。当 isTrick
为 false
时,传入 coins()
函数。对于第二次调用,当 isTrick
为 true
时,传入 cupcake()
函数。
好了,现在我们已经掌握了如何将函数作为参数。但是如果我们不想传入函数呢?答案是把函数类型声明为可为null
,方法很简单,用圆括号括住函数类型,并在后面接?
符号
修改trickOrTreat
函数:
fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
if (isTrick) {
return trick
} else {
if (extraTreat != null) {
println(extraTreat(5))
}
return treat
}
}
好了,现在extraTreat
可以为空了,并且只有它不为空的情况下才会调用println(extraTreat(5))
总结:
Kotlin 中的函数是一级结构,可以视为数据类型。
lambda 表达式提供了一种用于编写函数的简写语法。
您可以将函数类型传入其他函数。
对于一个函数类型,您可以从另一个函数返回它。
lambda 表达式会返回最后一个表达式的值。
简化Lambda表达式
1.省略参数名称
我们依然以上文中的coins
函数为例
val coins: (Int) -> String = {
quantity->"$quantity quarters"
}
coins
函数只接受一个Int
类型的参数,我们完全可以省略quantity
名称和->
符号,因为·Kotlin
会自动为其分配it
名称,就像这样
val coins: (Int) -> String = {
"$it quarters"
}
2.将lambda表达式直接传入函数
在上文中,我们将coins
函数作为参数传入trickOrTreat
h函数中:
fun main() {
val coins: (Int) -> String = {
"$it quarters"
}
val treatFunction = trickOrTreat(false, coins)
}
我们可以看到,coins
函数非常简短,并且只调用过一次,因此我们可以直接将lambda表达式传入其中,而不必再声明coins
函数
fun main() {
val treatFunction = trickOrTreat(false, { "$it quarters" })
treatFunction()
}
使用尾随lambda语法
当lambda表达式作为传入的组后一个参数时,可以把它写在括号外面,这样看起来会更加简洁
val treatFunction = trickOrTreat(false) { "$it quarters" }
对比一下
最初代码:
fun main() {
val coins: (Int) -> String = {
quantity->"$quantity quarters"
}
val treatFunction = trickOrTreat(false, coins)
}
简化版:
fun main() {
val treatFunction = trickOrTreat(false) { "$it quarters" }
}
这是lambda的一小步,是程序员的一大步
高阶函数
最后再简单说一下高阶函数,其实非常简单,高阶函数能够返回或接受另一个函数作为参数,例如,上篇文章中介绍的trickOrTreat()
函数就是一个高阶函数的示例,因为它接受 ((Int) -> String)?
类型的函数作为参数,并且返回了 () -> Unit
类型的函数。
fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
//接收函数作为参数
if (isTrick) {
return trick//返回函数
} else {
if (extraTreat != null) {
println(extraTreat(5))
}
return treat//返回函数
}
}
再来介绍一个非常有用的高阶函数:repeat
repeat(times: Int, action: (Int) -> Unit)
times
参数是操作应发生的次数。action
参数是一个接受单个 Int
参数并返回 Unit
类型的函数。action
函数的 Int
参数是到目前为止已执行的操作次数,例如第一次迭代的 0
参数或第二次迭代的 1
参数。您可以使用 repeat()
函数按指定次数重复执行代码,这与 for
循环类似。
使用示例:
fun main() {
val treatFunction = trickOrTreat(false) { "$it quarters" }
val trickFunction = trickOrTreat(true, null)
repeat(4) {
treatFunction()//对action函数使用尾随lambda语法
}
trickFunction()
}
运行后,treatFunction
即可执行四次
总结
只有一个参数的 lambda 表达式中,可以直接使用 it
标识符来引用它。如果调用函数的最后一个参数是函数类型,可以使用尾随 lambda 语法将 lambda 表达式移至最后一个圆括号后面。 高阶函数是指接受函数作为参数或返回函数的函数。