学不好Lambda,能学好Kotlin吗
嗯,当然
不能
进入正题,Kotlin中,高阶函数的身影无处不在,听上去高端大气上档次的高阶函数,简化一点讲,其实就是Lambda + 函数。
如果,Lambda学不好,就会导致高阶函数学不好,就会导致协程等等一系列的Kotlin核心学不好,Kotlin自然就一知半解了。所以,下面,一起来学习吧。
开始一个稍微复杂一点的实现
需求如下:传入一个参数,打印该参数,并且返回该参数
分析
乍看需求,这还不简单,一个print加一个return不就完事了,但是如果用Lambda,该怎么写呢?
val myPrint = { str: String ->
print("str is $str")
str
}
- 这里划第一个重点,Lambda的最后一行作为返回值输出。此时,如果直接打印myPrint,是可以直接输出的
fun main() {
println(myPrint("this is kotlin"))
}
结果和预想一致。如果对这种函数的写法结构有什么疑惑的,可以查看juejin.cn/post/701173…
String.()
一脸懵逼,这是啥玩意?(此处应有表情 尼克杨问号脸)
先写个例子看看
val testStr : String.() -> Unit = {
print(this)
}
- 官方一点解释,在.和()之间没有函数名,所以这是给String增加了一个匿名的扩展函数,这个函数的功能是打印String。在括号内,也就是Lambda体中,会持有String本身,也就是this。怎么调用呢?如下:
fun main() {
"hello kotlin".testStr()
}
// 执行结果:hello kotlin
- 此外这里还有一个重点:扩展函数是可以全局调用的
- 扩展函数有啥用?举个例子,如果对Glide提供的方法不满意,可以直接扩展一个Glide.xxx函数供自己调用,在xxx函数内部,可以取到this,也就是Glide本身。
- 有兴趣可以看一下Compose的源码,原来扩展函数还可以这么用
终极形态
先看代码
val addInt : Int.(Int) -> String = {
"两数相加的结果是${this + it}"
}
用已有的知识分析一下:
- Int.():匿名的扩展函数
- this:当前的Int,也就是调用这个扩展函数的对象
- "两数相加的结果是${this + it}" : Lambda的最后一行,也就返回值
如何调用
一般有如下两种调用方式:
fun main() {
println(addInt(1,2))
println(1.addInt(2))
}
- 第二种更加符合规范,之所以可以有第一种写法,是因为this会默认作为第一个参数
- 此处可以记住一个知识点,扩展了某一个函数,扩展函数内部的this就是被扩展的函数本身
Kotlin函数返回值那些事
在Kotlin函数中,如果不指定函数的返回值类型,则默认为Unit
fun output() {println("helle kotlin")}
- 上述函数的返回值为Unit类型
当函数体中出现return的时候,则需要手动为函数指定类型
fun output2() : Int {
return 0
}
- 返回Int类型的0,需要手动指定函数的返回值类型,否则报错
如果是以下的函数,那么返回值为?
fun output3() = {}
- 此处的返回值为() -> Unit,可省略,写全了,就是如下的样子:
fun output3() : () -> Unit = {}
- 此处函数返回函数,已经是高阶函数的范畴了
如果函数接着套一个函数呢,比如
fun output4() = run { println("hello kotlin") }
- 虽说run是一个函数,但是此处的返回值就不是() -> Unit
- 此处的返回就是run的返回值,但是run是什么?
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
- run的作用就是执行内部的函数,在这里就是println方法。
- run的返回自是R,也就是泛型,具体一点就是println的返回值,这里println的返回值是Unit,所以可以得出上面的output4的返回值就是Unit。
- 这里如果不是很懂的话,可以看一个简单一点的例子
fun output5() = run {true}
- 此处,函数的返回值就是true的类型,Boolen
函数中套一个函数怎么传参呢
刚刚的例子中,知道了怎么写一个函数中套函数,那么其中嵌套得函数怎么传参呢
fun output6() = {a: Int -> println("this is $a")}
- a为参数,函数是println,所以output6的返回值类型为(Int) -> Unit
- 如果需要调用的话,需要这么写:
output6()(1)
最后一个重点:在写Lambda的时候,记住换行
几种函数写法的区别
fun a()
常见的函数
val a = {}
a是一个变量,只不过是一个接受了匿名函数的变量,可以执行这个函数,和第一种现象一致。
这里的a还可以赋值给另一个变量 val a2 = a,但是函数本身不能直接赋给一个变量,可以使用::,让函数本身变成函数的引用
--end---
作者:鸣乔
链接:https://juejin.cn/post/7018184770873983007
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。