Kotlin 的魔力:`by` 关键字的作用及其如何简化代码?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:一个小操作符,一个大魔法

\n\n

你是否曾经在查看别人的 Kotlin 代码时,看到过像 val name by lazy { ... } 或 class Derived(Base by impl) 这样奇怪的构造?如果是,那你肯定问过自己:“Kotlin 中的 by 关键字到底是做什么的?”。这个问题是 Stack Overflow 上最热门的问题之一,这并不奇怪。by 不仅仅是语法糖,它是一个强大的 委托 机制,可以极大地简化你的代码,使其更整洁,并省去大量样板代码。

\n\n

在本文中,我们将全面解析 by。你将了解 属性委托 和 类委托 的工作原理。我们将回答初学者最常见的问题,并展示你可以在项目中立即使用的实际示例。开始吧!

\n\n

Kotlin 中的委托是什么?(核心理念)

\n\n

在深入细节之前,我们先理解其本质。委托 是一种设计模式,其中一个对象将其任务的执行交给另一个辅助对象。Kotlin 通过 by 关键字将这个模式直接内置于语言中。与其“手动”编写代码,不如告诉编译器:“嘿,让这个东西替我做所有事”。

\n\n

Kotlin 中有两种主要的委托类型:

\n
    \n
  • 属性委托 — 属性的 getter/setter 被交给另一个对象。
  • \n
  • 类委托 — 接口的实现被交给另一个对象。
  • \n
\n\n

这两种情况都使用同一个关键字 — by。让我们逐一解析。

\n\n

1. 属性委托:用于字段的 by

\n\n

这是 by 最流行的用法。它允许重用属性 getter 和 setter 的逻辑。你不必每次都编写重复的代码,而是使用现成的或自定义的 委托。

\n\n

示例 1:by lazy — 懒加载初始化

\n\n

假设你有一个创建起来很耗时的属性(例如,从网络加载数据)。你不想在创建类时计算它,而是想在第一次访问时计算。by lazy 正是为此而生:

\n\n
val heavyData: String by lazy {\n    println("正在计算数据...")\n    "一个非常耗时的结果"\n}\n\nfun main() {\n    println("开始")\n    println(heavyData) // 第一次调用:计算\n    println(heavyData) // 第二次调用:直接从缓存获取\n}
\n\n

输出:

\n
开始\n正在计算数据...\n一个非常耗时的结果\n一个非常耗时的结果
\n\n

这里发生了什么? 关键字 by 表示:“属性 heavyData 将其实现委托给对象 lazy { ... }”。该对象保证代码块仅在第一次访问时执行一次,然后缓存结果。这对于配置、数据库连接和其他“昂贵”的对象来说是理想的选择。

\n\n

示例 2:by observable — 监视变化

\n\n

想在每次属性更改时执行某个操作吗?使用标准库中的 Delegates.observable:

\n\n
import kotlin.properties.Delegates\n\nvar watchedValue: Int by Delegates.observable(0) { property, oldValue, newValue ->\n    println("旧值:$oldValue, 新值:$newValue")\n}\n\nfun main() {\n    watchedValue = 10  // 旧值:0, 新值:10\n    watchedValue = 42  // 旧值:10, 新值:42\n}
\n\n

这种模式对于 响应式编程、数据验证或 UI 同步来说是不可或缺的。顺便提一下,这里的 by 工作原理完全相同。

博客

书籍推荐