kotlin基础(4):Lambda表达式和函数类型
Lambda表达式和函数类型
将函数储存在变量中
如需将函数作为值引用,您需要使用函数引用运算符 (::)。语法如下图所示:

示例
fun main() {
val trickFunction = ::trick
}
fun trick() {
println("No treats!")
}
使用 lambda 表达式重新定义函数

此时若需引用:
fun main() {
val trickFunction = trick
trick()
}
val trick = {
println("No treats!")
}
fun main() {
val trickFunction = trick //没有::
trick() //调用函数
trickFunction()
}
val trick = {
println("No treats!")
}
输出应为
No treats!
No treats!
将函数用作数据类型
如果要指定函数参数的类型或返回值类型,则需要了解用于表达函数类型的语法。函数类型由一组圆括号组成,其中包含可选的参数列表、-> 符号和返回值类型。

val treat: () -> Unit = {
println("Have a treat!")
}
尝试调用:
fun main() {
val trickFunction = trick
trick()
trickFunction()
treat()
}
输出应为
No treats!
No treats!
Have a treat!
将函数用作返回值类型

尝试创建函数:
fun trickOrTreat(isTrick: Boolean): () -> Unit {
if (isTrick) {
return trick
} else {
return treat
}
}
val trick = {
println("No treats!")
}
val treat = {
println("Have a treat!")
}
从主函数调用:
fun main() {
val treatFunction = trickOrTreat(false)
val trickFunction = trickOrTreat(true)
}
您的输出应为
Have a treat!
No treats!
将一个函数作为参数传递到另一个函数
在世界上某些过万圣节的地区,孩子们会收到零钱(而非糖果),或者既能收到零钱,也能收到糖果。您将修改 trickOrTreat() 函数,以允许提供函数代表的其他招待内容作为参数
当您为接受参数的函数编写 lambda 表达式时,系统会按参数出现的先后顺序为参数命名。参数名称列在左大括号后面,各名称之间以英文逗号隔开。箭头 (->) 将参数名称与函数正文隔开。语法如下图所示:

将trickOrTreat修改为:
fun trickOrTreat(isTrick: Boolean, extraTreat: (Int) -> String): () -> Unit {
if (isTrick) {
return trick
} else {
println(extraTreat(5))
return treat
}
}
现在,当您调用 trickOrTreat() 函数时,需要使用 lambda 表达式定义一个函数并为 extraTreat 参数传入该函数。
在 main() 函数中,在对 trickOrTreat() 函数的调用前面添加一个 coins() 函数。coins() 函数为 Int 参数指定名称 quantity 并返回 String。
您可能会发现这里没有 return 关键字,lambda 表达式中无法使用该关键字。相反,函数中最后一个表达式的结果将成为返回值。
fun main() {
val coins: (Int) -> String = { quantity ->
"$quantity quarters"
}
val cupcake: (Int) -> String = { //移除 quantity 参数和 -> 符号。这里用不到它们
"Have a cupcake!"
}
val treatFunction = trickOrTreat(false)
val trickFunction = trickOrTreat(true)
treatFunction()
trickFunction()
}
运行您的代码。仅当 isTrick 参数设置为 false 实参时,系统才会调用 extraTreat() 函数,因此输出会包含 5 个 25 美分硬币,但不包含纸杯蛋糕。
5 quarters
Have a treat!
No treats!
可为 null 的函数类型
与其他数据类型一样,函数类型可声明为可为 null。在这些情况下,变量可以包含函数,也可以为 null。
如需将函数声明为可为 null,请用圆括号括住函数类型,并在右圆括号外后接 ? 符号。
例如,如果您想让 () -> String 类型可为 null,则将其声明为 (() -> String)? 类型。语法如下图所示:

将 extraTreat 参数设置为可为 null,这样您就不必在每次调用 trickOrTreat() 函数时都提供 extraTreat() 函数:
-
将
extraTreat参数的类型更改为(() -> String)?。fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit { -
将对
extraTreat()函数的调用修改为使用if语句,以便仅在该函数为非 null 时才调用该函数。现在,trickOrTreat()函数应如以下代码段所示:fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit { if (isTrick) { return trick } else { if (extraTreat != null) { println(extraTreat(5)) } return treat } } -
移除
cupcake()函数,然后在对trickOrTreat()的第二次调用中将cupcake参数替换为null。fun main() { val coins: (Int) -> String = { quantity -> "$quantity quarters" } val treatFunction = trickOrTreat(false, coins) val trickFunction = trickOrTreat(true, null) treatFunction() trickFunction() }
最终运行输出应为:
5 quarters
Have a treat!
No treats!
妙哉
使用简写语法编写 lambda 表达式
省略参数名称
在编写 coins() 函数时,您为函数的 Int 参数明确声明了名称 quantity。不过我们有更简单的方法,可以不用显式声明
如图:

Kotlin 中,单参数的 lambda 默认使用 it 作为参数名,因此你可以选择使用 $it 来引用传入的参数
即:可将coin函数更新为:
val coins: (Int) -> String = {
"$it quarters"
}
将 lambda 表达式直接传入函数
目前仅在一个位置使用了 coins() 函数。如果您只需将 lambda 表达式直接传入 trickOrTreat() 函数,而无需先创建变量呢?
流程如下:

尝试移除coins函数,并将语法替换至传参:
fun main() {
val treatFunction = trickOrTreat(false, { "$it quarters" })
val trickFunction = trickOrTreat(true, null)
treatFunction()
trickFunction()
}
运行应仍为
5 quarters
Have a treat!
No treats!
使用尾随 lambda 语法
(其实是传入参数的简化版)
逻辑如下:
即可以在 treatFunction 变量中,将 lambda 表达式 {"$it quarters"} 移到对 trickOrTreat() 的调用中的右圆括号后面。
val treatFunction = trickOrTreat(false) { "$it quarters" }
运行代码应该如常
使用 repeat() 函数
如果一个函数会返回或接受另一个函数作为实参,该函数就称为高阶函数。
trickOrTreat() 函数是一个高阶函数示例,因为它接受 ((Int) -> String)? 类型的函数作为参数,并返回 () -> Unit 类型的函数。
Kotlin 提供了几个有用的高阶函数,您可以利用新掌握的 lambda 知识对这些函数加以利用。
repeat() 函数就是这样一种高阶函数。repeat() 函数是使用函数表达 for 循环的简洁方式。在后续单元中,您会经常使用该函数以及其他高阶函数。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()
}
trickFunction()
}
输出为:
5 quarters
Have a treat!
Have a treat!
Have a treat!
Have a treat!
No treats!
总结
- Kotlin 中的函数是一级结构,可以视为数据类型。
- lambda 表达式提供了一种用于编写函数的简写语法。
- 您可以将函数类型传入其他函数。
- 对于一个函数类型,您可以从另一个函数返回它。
- lambda 表达式会返回最后一个表达式的值。
- 如果只有一个参数的 lambda 表达式中省略了某个参数标签,系统会使用
it标识符来引用它。 - lambda 可以内嵌方式编写,无需使用变量名称。
- 在您调用某个函数时,如果该函数的最后一个参数是函数类型,您可以使用尾随 lambda 语法将 lambda 表达式移至最后一个圆括号后面。
- 高阶函数是指接受函数作为参数或返回函数的函数。
repeat()函数是一个高阶函数,其工作方式与for循环类似。
更多推荐
所有评论(0)