一、apply

        apply 用于在某个对象上执行一系列操作,然后返回该对象本身。这通常用于链式调用,以简化代码。

        它被定义在 Any 类上,因此可以被任何类型的对象所使用。它接收一个 lambda 表达式作为参数,在这个 lambda 表达式中,this 关键字引用的是调用 apply 的对象。当你调用 apply 函数时,会传递当前对象 (this) 给 lambda 表达式。这意味着可以直接在 lambda 表达式内部访问并修改这个对象的属性和方法,而不需要显式地指定 this

        主要用途:是在构建和初始化对象时设置该对象的多个属性或执行多个操作,使得代码更加简洁和易读。

示例:

假设有一个 Person 类,想要创建一个 Person 对象并同时设置它的多个属性,可以这样使用 :

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

fun main() {
    val person = Person("John Doe", 30, "Unknown").apply {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
    }

    println(person)
}

apply 可以使初始化过程变得更加简洁。例如,对于 Person 类,你还可以在构造函数中使用 apply 来初始化属性:

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

fun main() {
    val person = Person("").apply {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
    }

    println(person)
}


在实际开发中,apply 常常用于初始化配置对象、构建复杂的对象结构等场景。例如,如果正在使用 Android 开发,并且需要配置一个 View,可以这样使用 apply:

val button = Button(context).apply {
    text = "Click me!"
    setOnClickListener {
        // 按钮点击事件
    }
}

二、also

        在 Kotlin 中,also 是一个扩展函数,它同样定义在 Any 类上,因此可以被任何类型的对象所使用。also 的主要用途是在不改变对象的情况下执行某些操作,通常是用于副作用操作,比如日志记录、调试输出或其他不影响对象状态的操作

        与 apply 不同的是,also 的主要目的是为了执行一些副作用操作,而不是修改对象本身。also 函数最终返回 Unit,这意味着它不会返回对象本身,而是执行完 lambda 表达式后结束

主要用途:

  1. 日志记录:在对象创建后记录对象的状态。
  2. 调试输出:输出对象的详细信息以便于调试。
  3. 其他不影响对象状态的操作。

示例

假设有一个 Person 类,要创建一个 Person 对象并在创建后立即输出一条日志信息,可以这样使用 also:

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

fun main() {
    val person = Person("John Doe", 30, "Unknown").also {
        println("Person created: ${it.name}, ${it.age}, ${it.address}")
    }

    println(person)
}

also 与 apply 的区别:

apply 和 also 都接收 this 作为参数,但它们的用途不同:

  1. apply 最终返回 this,这允许你继续链式调用。
  2. also 同样接收 this 作为参数,但它返回的是 Unit(即无返回值),通常用于副作用(side-effect)操作,比如打印调试信息。

示例对比:

在这个例子中,apply 被用来修改 Person 对象的属性,而 also 仅用于输出一条日志信息。

val person = Person("John Doe", 30, "Unknown").apply {
    name = "Jane Smith"
    age = 28
    address = "123 Main St"
}.also {
    println("Person initialized: $it")
}

println(person)

三、let

        在 Kotlin 中,let 是一个扩展函数,它同样定义在 Any 类上,因此可以被任何类型的对象所使用。

        当你调用 let 函数时,它会传递当前对象 (this) 给 lambda 表达式。如果对象是非空的,则执行 lambda 表达式;如果对象是 null,则不会执行 lambda 表达式,并且整个表达式的结果也是 null。

主要用途:是允许你基于某个条件来有条件地执行某些操作。它通常用于空安全检查、资源处理以及其他条件判断场景。

示例:

如果想要根据 Person 是否为空来执行不同的操作,可以这样使用 let

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

fun main() {
    val person: Person? = Person("John Doe", 30)

    // 如果 person 为 null,则不会执行 let 的块,而是执行 ?: 后面的代码
    person?.let {
        println("Person's name is ${it.name} and age is ${it.age}")
    } ?: println("No person available")

}

四、with

        在 Kotlin 中,with 是一个常用的扩展函数,它定义在 Any 类上,因此可以被任何类型的对象所使用。with 的主要用途是在给定的上下文中执行一系列操作,这些操作通常涉及同一个对象。with 的一个重要特点是它返回最后一个表达式的结果

工作原理:
        当你调用 with 函数时,它会将当前对象 (this) 作为上下文传递给 lambda 表达式。然后你可以在 lambda 表达式内部访问并操作这个对象。with 函数最终返回 lambda 表达式的结果。

示例

假设你有一个 Person 类,要在一个上下文中设置和使用这个对象的多个属性,可以这样使用:

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

fun main() {
    val person = with(Person("John Doe", 30, "Unknown")) {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
        this
    }

    println(person)
}

with 与 apply 的区别:

虽然 with 和 apply 都可以在一个上下文中执行一系列操作,但它们之间有几个关键的区别:

  1. with 返回 lambda 表达式的结果,而 apply 返回 this。
  2. with 可以用于任何对象,而 apply 通常用于对象自身的初始化或修改。
  3. with 更适合于执行一系列独立的操作,而 apply 更适合于对象本身的初始化或配置。

示例对比

下面是使用 with 和 apply 的示例对比:

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

fun main() {
    // 使用 with 来在一个上下文中设置和使用对象
    val person = with(Person("John Doe", 30, "Unknown")) {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
        this
    }

    println(person)

    // 使用 apply 来初始化对象
    val newPerson = Person("John Doe", 30, "Unknown").apply {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
    }

    println(newPerson)
}

五、run

        在 Kotlin 中,run 是一个扩展函数,它同样定义在 Any 类上,因此可以被任何类型的对象所使用。run 的主要用途是在给定的上下文中执行一系列操作,并返回最后一个表达式的结果。它结合了 with let 的特性,既可以在上下文中操作对象,也可以有条件地执行操作

工作原理:当你调用 run 函数时,它会将当前对象 (this) 作为上下文传递给 lambda 表达式。然后你可以在 lambda 表达式内部访问并操作这个对象。run 函数最终返回 lambda 表达式的结果。

示例:

假设你有一个 Person 类,你想要在一个上下文中设置和使用这个对象的多个属性,并有条件地执行某些操作,可以这样使用 run:

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

fun main() {
    val person = Person("John Doe", 30, null).run {
        name = "Jane Smith"
        age = 28
        address = "123 Main St"
        println("Person updated.")
        this
    }

    println(person)

    // 使用 run 进行空安全检查
    person.address?.run {
        println("Address: $this")
    } ?: println("No address available")
}

with和run的区别:

返回值:

  1. with 和 run 都返回 lambda 表达式的结果,但在上下文中使用的方式有所不同。
  2. with 通常用于执行一系列操作,而 run 除了执行操作外,还可以用于有条件地执行操作。

用途:

  1. with 更适合于执行一系列独立的操作,尤其是当这些操作都是针对同一个对象时。
  2. run 更适合于执行一系列操作并有条件地执行某些操作,尤其是在需要返回一个特定的结果时。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部