Kotlin 扩展函数 run , with , let , also 和 apply

本文深入解析Kotlin中的run、with、let、also、apply等函数的使用场景与区别,包括它们的作用域、接收者、传参及返回值特性,帮助读者理解并掌握这些函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数定义与使用

run()

定义

/**
 * Calls the specified function [block] and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

示例

fun runTest1() {
    var name = "AA"
    run {
        val name = "BB"
        Log.e(TAG, name) // BB
    }
    Log.d(TAG, name) // AA
}

run() 函数在 runTest1 函数中又提供了自己的作用域,并且 run() 函数中可以重新定义一个 name 变量,该变量只存在于 run() 函数中。以下介绍的几个函数和 run() 函数同理,都是提供了自己的作用域。

fun runTest2() {
    var success = true
    var result = run {
        if (success) {
            "200"
        } else {
            "404"
        }
    }
    Log.d(TAG, result) // 200
}

run() 返回作用域中的最后一个对象

T.run()

定义

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

示例

fun tRunTest() {
    val result = "ABCDEF".run {
        Log.d(TAG, "字符串的长度为$length") // 字符串的长度为6
        substring(2)
    }
    Log.d(TAG, result) // CDEF
}

T.run() 中通过 this 来获取 “ABCDEF” 对象,然后输出 length . T.run() 返回作用域中的最后一个对象

with()

定义

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

示例

fun withTest() {
    val result = with("ABCDEF") {
        substring(2)
    }
    Log.d(TAG, result) // CDEF
}

with() 返回作用域中的最后一个对象

T.let()

定义

/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

示例

fun letTest() {
    val result = "ABCDEF".let {
        it.substring(2) // it 代表 "ABCDEF"
    }
    Log.d(TAG, result) // CDEF
}

T.let() 返回作用域中的最后一个对象

T.also()

定义

/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

示例

fun alsoTest() {
    val  result = "ABCDEF".also {
        it.substring(2) // it 代表 "ABCDEF"
    }
    Log.d(TAG, result) // ABCDEF
}

T.also() 返回原来的对象不变

T.apply()

定义

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

示例

fun applyTest() {
    val result = "ABCDEF".apply {
        this.substring(2) // this 代表 "ABCDEF"
    }
    Log.d(TAG, result) // ABCDEF
}

T.apply() 返回原来的对象不变

函数特点

T.run()、T.run()、T.also()、T.apply() 函数

xxx 表示函数名

class MyClass {
    fun test() {
        val str = "AA"
        val result = str.xxx {
            print(this) // 接收者
            print(it) // 传参
            100 // 返回值
        }
        print(result)
    }
}
函数接收者(this)传参(it)返回值(result)
T.run()“AA”编译错误作用域中的最后一个对象
T.let()this@Myclass“AA”作用域中的最后一个对象
T.also()this@Myclass“AA”“AA” 对象(本身)
T.apply()“AA”编译错误“AA” 对象(本身)

run() 与 with(T) 函数

class MyClass {
    fun runTest() {
        var result = run {
            print(this) // 接收者
            print(it) // 传参
            100 // 返回值
        }
        print(result)
    }

    fun withTest() {
        val str = "AA"
        var result = with(str) {
            print(this) // 接收者
            print(it) // 传参
            100 // 返回值
        }
        print(result)
    }
}
函数接收者(this)传参(it)返回值(result)
run()this@Myclass编译错误作用域中的最后一个对象
with()“AA”编译错误作用域中的最后一个对象

函数特点汇总

函数接收者(this)传参(it)返回值(result)
T.run()“AA”编译错误作用域中的最后一个对象
run()this@Myclass编译错误作用域中的最后一个对象
with()“AA”编译错误作用域中的最后一个对象
T.let()this@Myclass“AA”作用域中的最后一个对象
T.also()this@Myclass“AA”“AA” 对象(本身)
T.apply()“AA”编译错误“AA” 对象(本身)

函数选择

Mou icon

参考资料:

Kotlin基础 — 操作符:run、with、let、also、apply、takeIf、takeUnless、repeat

Kotlin 操作符:run、with、let、also、apply 的差异与选择

聊一聊Kotlin扩展函数run,with,let,also和apply的使用和区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值