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 反馈 — 无需本地设置。