在 Kotlin 中,扩展函数 和带接收者的 Lambda 表达式是强大的特性,允许你为现有类添加新功能或创建类型安全的 DSL。以下是详细解释和示例:
1. 扩展函数(Extension Functions)
扩展函数允许在不修改类源码的情况下添加新函数:
kotlin
// 为 String 添加扩展函数
fun String.addExclamation(): String = "$this!"
fun main() {
println("Hello".addExclamation()) // 输出: Hello!
}
2. 带接收者的 Lambda(Lambda with Receiver)
带接收者的 Lambda 是一个特殊的函数类型,其内部可以直接访问接收者对象的成员(类似扩展函数的作用域)。语法为:T.() -> Unit
。
示例:标准库中的 apply
scss
val sb = StringBuilder().apply {
append("Hello") // 直接访问 StringBuilder 的方法
append(" World")
}
3. 自定义带接收者的扩展函数
你可以定义接收带接收者 Lambda 作为参数的扩展函数:
示例:为 StringBuilder
添加自定义构建器
kotlin
// 接收一个带 StringBuilder 接收者的 Lambda
fun buildString(action: StringBuilder.() -> Unit): String {
val sb = StringBuilder()
sb.action() // 执行 Lambda,sb 成为接收者
return sb.toString()
}
fun main() {
val result = buildString {
append("Kotlin") // 在 Lambda 内直接调用 append
append(" is ")
append("awesome!")
}
println(result) // 输出: Kotlin is awesome!
}
4. DSL 应用示例
带接收者的 Lambda 常用于创建类型安全的 DSL(领域特定语言):
示例:HTML 构建器
kotlin
class HTML {
fun body(action: Body.() -> Unit) { /*...*/ }
}
class Body {
fun div(action: Div.() -> Unit) { /*...*/ }
}
class Div {
fun p(text: String) { /*...*/ }
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init() // 执行初始化 Lambda
return html
}
// 使用 DSL 构建 HTML
val myHtml = html {
body {
div {
p("Hello Kotlin DSL!")
}
}
}
关键语法总结
概念 | 语法 | 说明 |
---|---|---|
扩展函数 | fun T.myFunc() { ... } |
为类型 T 添加新函数 |
带接收者的 Lambda 类型 | T.() -> Unit |
Lambda 内部 this 指向 T 的实例 |
调用带接收者的 Lambda | receiver.action() |
将 receiver 作为接收者执行 Lambda |
DSL 风格调用 | receiver { ... } |
Lambda 块内直接访问接收者的成员 |
通过结合扩展函数和带接收者的 Lambda,你可以创建出高度可读且类型安全的 API,非常适合构建 DSL 或简化复杂对象的初始化。