HOWTO · Kotlin

在 Kotlin 中使用 by 关键字

Kotlin by 关键字是为委派目的而引入的新关键字。本文介绍了 by 关键字及其在 Kotlin 中的使用。

本页内容

Kotlin 中的 by 是一个软关键字,这意味着它作为关键字和基于上下文的标识符都很有用。by 关键字表示由提供。

Kotlin 自动为每个属性创建 getter()setter()。当我们定义一个 var 属性时,它会获得一个 get()set() 方法,而 val 属性默认会获得一个 get() 方法。

当我们想在其他地方定义这些方法时,Kotlin by 关键字会很有帮助,比如在函数初始化期间而不是在属性初始化期间。

当我们使用 by 关键字时,get()set() 方法由关键字后面的函数提供,而不是默认方式,这意味着它们是委托的。

在 Kotlin 中使用 by 关键字

by 关键字在两个地方很有帮助:(i) 将接口的实现委托和 (ii) 将属性的访问器委托给另一个对象。

如上所述,它用于委托属性的实现。

语法:

val/var <property_Name>: <Type> by <expression>

Kotlin by 关键字与属性的最常见用法是:

  • 懒惰的属性
  • 可观察的属性
  • 在地图中存储属性

在实现与另一个对象的接口时,它的工作方式类似,但有一些主要区别。

  1. 在提供函数的地方定义 by 关键字而不是函数
  2. 由于是和接口一起使用,所以也是实现继承的有效替代方案

使用 by 关键字将属性的实现委托给 Kotlin 中的另一个对象

本节将通过 Kotlin by 关键字的示例来为每个用例委托属性。

在 Kotlin 中使用带有惰性属性的 by 关键字

在 Kotlin 中,lazy() 函数将 lambda 作为输入并返回 Lazy 属性的实例。

使用 by 关键字时,第一个 get() 函数调用会执行 lambda 表达式并临时存储结果。第二个 get() 函数调用返回结果。

这是一个示例来演示它是如何工作的。

val exampleVal: String by lazy {
    println("initial!")
    "Welcome"
}

fun main() {
    println(exampleVal)
    println(exampleVal)
}

输出:

通过具有惰性属性的关键字使用 Kotlin

在 Kotlin 中使用具有可观察属性的 by 关键字

这是一个示例,展示了 Kotlin by 关键字如何与可观察属性一起使用。

import kotlin.properties.Delegates

class Student {
    var Name: String by Delegates.observable("David") {
        value, oldValue, newValue ->
        println("$oldValue -> $newValue")
    }
}

fun main() {
    val stud = Student()
    stud.Name = "John"
    stud.Name = "Doe"
}

输出:

通过具有可观察属性的关键字使用 Kotlin

如输出所示,可观察属性采用两个参数:初始值和修改处理程序。

每次我们为属性赋值时,处理程序都会运行。因此,我们在赋值之后有三个参数:用于赋值的初始属性、旧值和新值。

在 Kotlin 的地图中使用 by 关键字存储属性

在地图中存储属性允许执行动态任务,例如解析 JSON。这是一个示例,展示了我们如何委托属性并将它们存储在地图上。

class Student(val map_example: Map<String, Any?>) {
    val name: String by map_example
    val ID: Int     by map_example
}

fun main() {
    val s = Student(mapOf(
        "name" to "John Doe",
        "ID"  to 301
    ))
    println(s.name)
    println(s.ID)
}

输出:

通过关键字使用 Kotlin 在地图中存储属性

使用 by 关键字将接口的实现委托给 Kotlin 中的另一个对象

除了委托给属性,Kotlin by 关键字还允许将接口委托给另一个对象。这是一个例子来证明这一点。

当一个类与 by 关键字一起使用时,它通过将所有公共成员委托给特定对象来实现一个接口。

interface Parent {
    fun print()
}

class ParentImpl(val x: Int) : Parent {
    override fun print() { print(x) }
}

class Child(p: Parent) : Parent by p

fun main() {
    val p = ParentImpl(25)
    Child(p).print()
}

输出:

通过接口委派的关键字使用 Kotlin