返回

Kotlin里差异分析,let、run、with、apply和also

Android

作用域函数 是Kotlin比较重要的一个特性,共分为以下5种:

  • let
  • run
  • with
  • apply
  • also

这五个函数的工作方式可以说非常相似,但是我们需要了解的是这5种函数的差异,以便在不同的场景下做出合理的选择。

1. let

let函数的作用是将一个对象作为参数,然后在该对象的作用域内执行一段代码。let函数的语法如下:

fun <T> T.let(block: (T) -> R): R

其中:

  • T:对象类型
  • block:在对象的作用域内执行的代码块
  • R:代码块的返回值类型

例如,我们可以使用let函数来检查一个字符串是否为空:

val string: String? = "Hello"

string?.let {
    println(it)
}

这段代码首先检查string变量是否为null,如果不是null,则执行let函数中的代码块,并将string变量作为参数传递给代码块。代码块中的println函数将打印string变量的值。

2. run

run函数的作用与let函数类似,也是将一个对象作为参数,然后在该对象的作用域内执行一段代码。但是,run函数的语法与let函数略有不同:

fun <T, R> T.run(block: T.() -> R): R

其中:

  • T:对象类型
  • R:代码块的返回值类型
  • block:在对象的作用域内执行的代码块

例如,我们可以使用run函数来获取一个字符串的长度:

val string: String = "Hello"

val length = string.run {
    this.length
}

println(length)

这段代码首先将string变量作为参数传递给run函数,然后在run函数的代码块中获取string变量的长度。最后,将获取到的长度打印出来。

3. with

with函数的作用是将一个对象作为参数,然后在该对象的作用域内执行一段代码。但是,with函数的语法与let函数和run函数都有所不同:

fun <T, R> with(receiver: T, block: T.() -> R): R

其中:

  • T:对象类型
  • R:代码块的返回值类型
  • receiver:作为参数的对象
  • block:在对象的作用域内执行的代码块

例如,我们可以使用with函数来修改一个字符串的值:

val string: String = "Hello"

with(string) {
    this.replace("Hello", "World")
}

println(string)

这段代码首先将string变量作为参数传递给with函数,然后在with函数的代码块中将string变量的值修改为"World"。最后,将修改后的string变量打印出来。

4. apply

apply函数的作用是将一个对象作为参数,然后在该对象的作用域内执行一段代码。但是,apply函数的语法与let函数、run函数和with函数都有所不同:

fun <T> T.apply(block: T.() -> Unit): T

其中:

  • T:对象类型
  • block:在对象的作用域内执行的代码块

例如,我们可以使用apply函数来初始化一个对象:

class Person(val name: String, val age: Int)

val person = Person("John", 25).apply {
    this.age++
}

println(person.age)

这段代码首先创建一个Person对象,然后使用apply函数在该对象的作用域内将age变量的值加1。最后,将age变量的值打印出来。

5. also

also函数的作用是将一个对象作为参数,然后在该对象的作用域内执行一段代码。但是,also函数的语法与let函数、run函数、with函数和apply函数都有所不同:

fun <T> T.also(block: (T) -> Unit): T

其中:

  • T:对象类型
  • block:在对象的作用域内执行的代码块

例如,我们可以使用also函数来打印一个对象的属性:

val person = Person("John", 25)

person.also {
    println(it.name)
    println(it.age)
}

这段代码首先创建一个Person对象,然后使用also函数在该对象的作用域内打印该对象的name属性和age属性。

6. 总结

以下表格总结了let、run、with、apply和also这5种作用域函数的区别:

函数 语法 作用
let fun T.let(block: (T) -> R): R 将一个对象作为参数,然后在该对象的作用域内执行一段代码,并返回代码块的返回值
run fun <T, R> T.run(block: T.() -> R): R 将一个对象作为参数,然后在该对象的作用域内执行一段代码,并返回代码块的返回值
with fun <T, R> with(receiver: T, block: T.() -> R): R 将一个对象作为参数,然后在该对象的作用域内执行一段代码,并返回代码块的返回值
apply fun T.apply(block: T.() -> Unit): T 将一个对象作为参数,然后在该对象的作用域内执行一段代码,并返回该对象本身
also fun T.also(block: (T) -> Unit): T 将一个对象作为参数,然后在该对象的作用域内执行一段代码,并返回该对象本身

7. 使用场景

let、run、with、apply和also这5种作用域函数都有各自的适用场景。

  • let 函数适用于需要检查一个对象是否为null的情况,或者需要在对象不为null的情况下执行一段代码的情况。
  • run 函数适用于需要在对象的作用域内执行一段代码,并返回代码块的返回值的情况。
  • with 函数适用于需要在对象的作用域内执行一段代码,并返回该对象本身的情况。
  • apply 函数适用于需要初始化一个对象,或者在对象的作用域内执行一段代码,并返回该对象本身的情况。
  • also 函数适用于需要在对象的作用域内执行一段代码,并返回该对象本身的情况。

8. 性能

let、run、with、apply和also这5种作用域函数的性能都非常相似。在大多数情况下,我们都可以根据自己的喜好来选择使用哪种函数。

9. 总结

作用域函数是Kotlin比较重要的一个特性,共分为以下5种:let、run、with、apply以及also,这五个函数的工作方式可以说非常相似,但是我们需要了解的是这5种函数的差异,以便在不同的场景下做出合理的选择。另外,本文还提供了一些使用示例,帮助您进一步理解这些作用域函数的用法。