Cherry's Blog
497 words
2 minutes
Kotlin内联函数

代码环境#

在本文之后的代码中,默认省略以下代码

class Calculator {
    var a: Int = 0
    var b: Int = 0
    fun add() = a + b
    fun multiply() = a * b
}

fun main() {
    val calculator = Calculator()
    doCalculation(calculator)
}

run#

run的标准函数形式#

fun doCalculation(calculator: Calculator) {
    val result = run {
        calculator.a = 1
        calculator.b = 2
        calculator.add()
    }
    println(result)
}

run的标准函数形式能够在Lambda中执行操作,并返回一个结果,此结果即为Lambda中最后一行表达式

run的扩展函数形式#

fun doCalculation(calculator: Calculator) {
    val result = calculator.run {
        a = 1
        b = 2
        add()
    }
    println(result)
}

run此时被定义为接收者的扩展函数,它能够接收一个带有接收者(reciver)的Lambda

reciver中,能够访问调用者的上下文

with#

在with内处理结果#

fun doCalculation(calculator: Calculator) {
    val resultOne = with(calculator) {
        a = 1
        b = 2
        add()
    }
    println(resultOne)
}

with中也拥有reciver(接收者)

此时with的最后一个表达式即为with的返回值

若要让代码返回到with,而不是直接return整个函数,可以使用return@with

在with外处理结果#

fun doCalculation(calculator: Calculator) {
    with(calculator) {
        a = 3
        b = 4
    }
    val resultTwo = calculator.add()
    println(resultTwo)
}

在这一种处理方式中,with仅用于对对象统一的操作,而不直接返回值

apply#

fun doCalculation(calculator: Calculator) {
    val result = calculator.apply {
        a = 1
        b = 2
    }.add()
    println(result)
}

在apply的Lambda中,同样存在着接收者(reciver) 在apply函数中,Lambda在调用过后将会返回函数自身,因此不会打断函数后面的调用链

let#

fun main(){
    val values = listOf("aaaa", "bbbbb", null, "ccccccc", "ddddd", null)
    for (str in values) {
        str?.let { println(it) }
    }
}

let对应着run,为run不含有reciver的版本 通过使用?配合let,能够确保空安全

also#

fun doCalculation(calculator: Calculator) {
    val result = calculator.apply {
        a = 1
        b = 2
    }.add().also { println(it) }.times(5) // .times()实际上就是 * 的重载函数
    println(result)
}

also对应着apply,为apply不含有reciver的版本

also同样返回调用者本身,不会打断调用链

Kotlin内联函数
https://fuwari.vercel.app/posts/inline-functions/
Author
HyperCherry
Published at
2023-07-20