0Pricing
Kotlin Academy · 课时

by 关键字

委托接口实现

by 关键字 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。

什么是委托

类委托允许一个对象将接口的实现交给另一个对象。Kotlin 通过 by 关键字将这一功能内置到语言中。

它让组合变得轻松。

要委托的接口

先从一个接口和一个具体实现开始。稍后我们会将工作委托给这个实现。

interface Speaker {
    fun speak(): String
}

class LoudSpeaker : Speaker {
    override fun speak() = "HELLO!"
}

fun main() {
    println(LoudSpeaker().speak())
}

委托关键字

请编写 class X(d: Iface) : Iface by d。编译器会生成转发方法,为接口的每个成员调用 d。

interface Speaker {
    fun speak(): String
}

class LoudSpeaker : Speaker {
    override fun speak() = "HELLO!"
}

class Announcer(s: Speaker) : Speaker by s

fun main() {
    val a = Announcer(LoudSpeaker())
    println(a.speak())
}

无需样板代码

如果没有 by,您必须手动为接口的每个函数编写转发方法。委托会自动生成所有这些方法。

interface Repository {
    fun save(item: String): String
    fun count(): Int
}

class MemoryRepo : Repository {
    private val items = mutableListOf<String>()
    override fun save(item: String): String { items.add(item); return item }
    override fun count() = items.size
}

class LoggingRepo(r: Repository) : Repository by r

fun main() {
    val repo = LoggingRepo(MemoryRepo())
    repo.save("a")
    println(repo.count())
}

重写指定成员

您可以只重写需要自定义的成员,其余成员仍会转发给委托对象。

interface Repository {
    fun save(item: String): String
    fun count(): Int
}

class MemoryRepo : Repository {
    private val items = mutableListOf<String>()
    override fun save(item: String): String { items.add(item); return item }
    override fun count() = items.size
}

class LoggingRepo(private val r: Repository) : Repository by r {
    override fun save(item: String): String {
        println("saving " + item)
        return r.save(item)
    }
}

fun main() {
    val repo = LoggingRepo(MemoryRepo())
    repo.save("book")
    println(repo.count())
}

将委托对象作为参数

委托对象通常通过主构造函数传入。如果您还要重写某些成员,可以使用 private val 保存一个引用。

interface Clock { fun now(): Int }

class FixedClock : Clock { override fun now() = 12 }

class App(private val clock: Clock) : Clock by clock

fun main() {
    println(App(FixedClock()).now())
}

委托标准接口

您可以委托给内置的集合接口,从而立即获得一个行为类似底层集合的包装器。

class TaggedList(private val inner: List<String>) : List<String> by inner {
    val tag = "v1"
}

fun main() {
    val tl = TaggedList(listOf("x", "y"))
    println(tl.size)
    println(tl[0])
    println(tl.tag)
}

编译方式

在幕后,编译器会存储委托对象并生成转发实现。生成的方法只需调用委托对象中对应的方法。这与手写转发完全相同,只是省去了手动编写代码。

捕获的快照

有一个重要的细节:委托对象的引用会在构建对象时被捕获。重写的成员会显式调用委托对象,但生成的转发方法使用的是最初提供的实例。

interface Source { fun value(): Int }

class Const(val n: Int) : Source { override fun value() = n }

class Wrapper(s: Source) : Source by s

fun main() {
    val w = Wrapper(Const(42))
    println(w.value())
}

为什么使用委托关键字

by 关键字可以让您:

  • 复用现有实现
  • 无需继承即可添加行为
  • 避免脆弱的继承层次结构

这是 Kotlin 对“组合优于继承”原则的一等支持。

基础

这个 by 委托关键字是一切课程内容的基础。接下来,我们将更仔细地了解如何委托给成员对象来组合行为。

快速检查

请检验您对委托关键字的理解。

回顾

您学到了使用 by 进行类委托:

  • 将接口委托给另一个对象
  • 自动生成转发方法
  • 在转发其余成员的同时重写指定成员
  • 同样适用于内置接口

下一步:委托给成员来组合行为。

常见问题解答

「by 关键字」课时是免费的吗?

是的 — 「by 关键字」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。

「by 关键字」这节课中我会学到什么?

委托接口实现 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Kotlin Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「by 关键字」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Kotlin Academy 课中编写并运行代码吗?

能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. by 关键字
  2. 委托给成员
  3. 委托与继承
  4. 实用模式
← 返回 Kotlin Academy