Z
ZHANK
实用技巧

DSL 构建

类型安全的构建器、@DslMarker、lambda with receiver

DSL 构建

Kotlin 的 lambda with receiver 让构建类型安全的 DSL 变得自然——Gradle Kotlin DSL 就是例子。

学完本章你将: 掌握 lambda with receiver、@DslMarker、HTML DSL。


lambda with receiver

kotlin
fun buildString(action: StringBuilder.() -> Unit): String {
    val sb = StringBuilder()
    sb.action()
    return sb.toString()
}

val result = buildString {
    append("Hello, ")
    append("World!")
}
// "Hello, World!"

简单 HTML DSL

kotlin
class HTML {
    private val children = mutableListOf<String>()

    fun body(block: Body.() -> Unit) {
        val body = Body()
        body.block()
        children.add("<body>${body.content}</body>")
    }

    override fun toString() = children.joinToString("\n")
}

class Body {
    var content = ""
    fun p(text: String) { content += "<p>$text</p>\n" }
    fun h1(text: String) { content += "<h1>$text</h1>\n" }
}

fun html(block: HTML.() -> Unit): HTML {
    return HTML().apply(block)
}

val page = html {
    body {
        h1("标题")
        p("段落内容")
    }
}

@DslMarker

kotlin
@DslMarker
annotation class HtmlDsl

@HtmlDsl
class HTML { ... }

// 防止隐式访问外层接收者——避免混乱