构建类似 DSL 的 API
使用中缀调用提升清晰度
构建类似 DSL 的 API 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
用于清晰表达的中缀函数
中缀函数是 Kotlin DSL(领域特定语言)的构建基础。它们能让接口调用读起来像自然短语。
infix fun String.eq(value: String) = this == value
fun main() {
println("on" eq "on")
}流畅构建器的思路
将中缀函数与小型类型结合,可以用声明式方式表达意图。
class Query(val field: String) {
infix fun equals(value: String) = "$field = '$value'"
}
fun main() {
val q = Query("name") equals "Sam"
println(q)
}基于二元组的配置
中缀 to 函数让配置映射更易读。
fun configure(vararg opts: Pair<String, Any>) = opts.toMap()
fun main() {
val cfg = configure("debug" to true, "level" to 3)
println(cfg)
}范围 DSL
借助中缀函数,范围构建器读起来就像英语句子。
fun main() {
val r = 1 until 10 step 2
println(r.toList())
}组合条件
您可以使用中缀函数构造易读的类布尔短语。
data class Rule(val ok: Boolean) {
infix fun and(other: Rule) = Rule(ok && other.ok)
}
fun main() {
val result = Rule(true) and Rule(false)
println(result.ok)
}带接收者的匿名函数
真正的 DSL 通常会将中缀函数与带接收者的匿名函数结合起来,让一个代码块直接配置对象。
class Html {
val parts = mutableListOf<String>()
fun p(text: String) { parts.add("<p>$text</p>") }
}
fun html(block: Html.() -> Unit): Html {
val h = Html()
h.block()
return h
}
fun main() {
val page = html { p("Hi") }
println(page.parts)
}解释带接收者的匿名函数
像 Html.() -> Unit 这样的函数类型,会让代码块仿佛在 Html 实例内部运行,因此无需前缀即可调用成员。
class Box { var value = 0 }
fun box(init: Box.() -> Unit): Box {
val b = Box()
b.init()
return b
}
fun main() {
val b = box { value = 42 }
println(b.value)
}将 apply 用作小型 DSL
标准的 apply 函数本身就是一个用于配置对象的带接收者匿名函数 DSL。
class Server {
var host = ""
var port = 0
}
fun main() {
val s = Server().apply {
host = "localhost"
port = 8080
}
println("${s.host}:${s.port}")
}保持 DSL 的可读性
优秀的 DSL 会尽量减少冗余。请优先选择能让调用位置读起来像意图描述的名称。
data class Style(var bold: Boolean = false)
fun style(block: Style.() -> Unit) = Style().apply(block)
fun main() {
val s = style { bold = true }
println(s.bold)
}中缀函数加匿名函数
将中缀函数与匿名函数结合,可以构建表达力强的构建器。
class Table {
val rows = mutableListOf<String>()
infix fun row(text: String) { rows.add(text) }
}
fun table(block: Table.() -> Unit) = Table().apply(block)
fun main() {
val t = table {
row("A")
row("B")
}
println(t.rows)
}何时构建 DSL
对于重复且结构化的配置(用户界面、构建器、测试),DSL 很有价值。对于一次性逻辑,普通函数更简单。
fun main() {
val list = buildList {
add(1)
add(2)
}
println(list)
}快速检查
请检验您对类 DSL 接口的理解。
回顾
您学会了构建类 DSL 接口:
- 中缀函数让调用读起来像短语。
- 带接收者的匿名函数(
Type.() -> Unit)让代码块可以直接配置对象。 apply和buildList是标准库中的 DSL。- 请将 DSL 用于结构化的重复配置,并保持其可读性。
class C { var x = 0 }
fun c(b: C.() -> Unit) = C().apply(b)
fun main() {
println(c { x = 9 }.x)
}常见问题解答
「构建类似 DSL 的 API」课时是免费的吗?
是的 — 「构建类似 DSL 的 API」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「构建类似 DSL 的 API」这节课中我会学到什么?
使用中缀调用提升清晰度 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「构建类似 DSL 的 API」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 中缀函数
- 构建类似 DSL 的 API
- tailrec 函数
- 何时使用哪个函数