是否可以在 lambda 的闭包中隐藏变量?

Is it possible to hide variables from lambda's closure?

提问人:Alexey Pomelov 提问时间:9/13/2016 更新时间:3/24/2018 访问量:335

问:

我正在尝试在 Kotlin 中构建一个类型安全的时髦风格构建器,就像这里描述的那样。 问题在于嵌套 lambda 中 lambda 接收器的可见性。 这是一个简单的例子。

html {
    head(id = "head1")
    body() {
        head(id = "head2")
    }
}

嵌套 lambda 的接收器是没有“head”方法的 Body。尽管如此,此代码还是编译并打印为:

<html>
    <head id="head1"></head>
    <head id="head2"></head>
    <body></body>
</html>

这是意料之中的,但是有没有办法在内头上出现编译错误?

lambda kotlin 类型-安全 构建器-模式

评论

2赞 Ruckus T-Boom 9/13/2016
如果您愿意,有一个解决方法:stackoverflow.com/a/37000303/2094298

答:

4赞 yole 9/13/2016 #1

从 Kotlin 1.0 开始,这是不可能的。此功能有一个开放的功能请求

3赞 zsmb13 3/24/2018 #2

自 Kotlin 1.1 以来,这是可能的,这要归功于 @DslMarker 注解的引入

下面是如何使用它的示例:

@DslMarker
annotation class MyHtmlDsl

@MyHtmlDsl
class HeadBuilder

@MyHtmlDsl
class BodyBuilder

@MyHtmlDsl
class HtmlBuilder {
    fun head(setup: HeadBuilder.() -> Unit) {}
    fun body(setup: BodyBuilder.() -> Unit) {}
}

fun html(setup: HtmlBuilder.() -> Unit) {}

fun main(args: Array<String>) {
    html {
        head {}
        body {
            head { } // fun head(...) can't be called in this context by implicit receiver
        }
    }
}

另请参阅上面链接的公告中的文档。