kotlin中let、run、apply的区别

Kotlin 中的 letrunapply 都是 Scope Functions(作用域函数),用于限定一个代码块的作用域。它们的区别在于返回值和使用场景上。

一. 语法

1. let 函数:

源码:

// 参数 block: (T) -> R 普通的函数类型
public inline fun <T, R> T.let(block: (T) -> R): R {
    
    
    contract {
    
    
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

语法:

object.let {
    
    
    // 在此处使用 object
}

let 函数是将一个对象作为 lambda 表达式的参数,在 lambda 表达式内部可以通过 it 引用这个对象。它的返回值是 lambda 表达式的执行结果。

let 函数适合对一个对象进行一系列处理,并返回处理结果的场景。

2. run 函数:

源码:

// 参数block: T.() -> R 是一个带有接收者的函数类型
public inline fun <T, R> T.run(block: T.() -> R): R {
    
    
    contract {
    
    
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

语法:

object.run {
    
    
    // 在此处使用 object
}

run 函数是将一个对象作为 lambda 表达式的接收者,在 lambda 表达式内部可以通过 this 或省略掉 this 直接访问对象的方法和属性。它的返回值是 lambda 表达式的执行结果。

run 函数适合对一个对象进行一系列处理,并返回处理结果的场景。它和 let 函数的不同在于,run 函数将 lambda 表达式的执行结果作为返回值,而 let 函数将 lambda 表达式的参数作为返回值。

3. apply 函数:

源码:

// 返回的是对象自己
public inline fun <T> T.apply(block: T.() -> Unit): T {
    
    
    contract {
    
    
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

语法:

object.apply {
    
    
    // 在此处使用 object
}

apply 函数是将一个对象作为 lambda 表达式的接收者,在 lambda 表达式内部可以通过 this 或省略掉 this 直接访问对象的方法和属性。它的返回值是对象本身。

apply 函数适合对一个对象进行一系列操作,例如初始化对象的属性,而不需要返回结果的场景。因为它返回的是对象本身,所以可以使用链式调用。

二. 使用场景

1. let 的使用场景

假设有一个字符串,我们想要将它转换成大写并打印出来,可以使用 let 函数来实现:

val str = "hello world"
str.let {
    
    
    it.toUpperCase()
}.let {
    
    
    println(it)
}

在这个例子中,我们首先调用了 let 函数,并将字符串 str 作为参数传入,然后在 lambda 表达式内部调用了 toUpperCase() 方法将字符串转换成大写,并将结果返回。由于 let 函数的返回值就是 lambda 表达式的执行结果,所以我们可以继续链式调用另一个 let 函数,并在其内部打印出转换后的字符串。

2. run 的使用场景

假设有一个可空的字符串,我们想要在它不为空的情况下将它转换成大写并打印出来,可以使用 run 函数来实现:

val str: String? = "hello world"
str?.run {
    
    
    toUpperCase()
}.run {
    
    
    println(this)
}

在这个例子中,我们首先通过安全调用运算符 ?. 判断字符串是否为空,如果不为空则将其作为 lambda 表达式的接收者,调用 toUpperCase() 方法将字符串转换成大写,并返回结果。由于 run 函数将 lambda 表达式的执行结果作为返回值,所以我们可以继续链式调用另一个 run 函数,并在其内部打印出转换后的字符串。

3. apply 的使用场景

假设有一个 Person 类,我们想要创建一个实例并初始化它的属性,可以使用 apply 函数来实现:

data class Person(var name: String, var age: Int)

val person = Person("", 0).apply {
    
    
    name = "Tom"
    age = 18
}

在这个例子中,我们首先调用了 apply 函数,并将一个空的 Person 实例作为参数传入,然后在 lambda 表达式内部对其属性进行初始化,最后返回初始化后的 Person 实例。由于 apply 函数的返回值就是对象本身,所以我们可以将其赋值给一个变量 person 并直接使用它。

猜你喜欢

转载自blog.csdn.net/flytosky21/article/details/129962172