学不好Lambda,能学好Kotlin吗

·  阅读 942
学不好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"))
}
复制代码

image.png

结果和预想一致。如果对这种函数的写法结构有什么疑惑的,可以查看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---

分类:
Android
标签: