你能在 Kotlin 中以 运行 的时间连接语句吗?

Can you concatenate statements at run-time in Kotlin?

我正在尝试使用 Kotlin-DSL 与 TeamCity 交互

In this section 在 TC Kotlin 指南中有一个看起来很奇怪的部分,它似乎导致语句在运行中连接起来。

它首先定义了这些:

val linux = Requirements() {
   contains("os.name", "linux")
}

val oracle = Requirements() {
   equals("db.name", "oracle")
}

val java6 = Requirements() {
   contains("env.JAVA_HOME", "1.6")
}

然后使用这些定义执行此操作:

buildType {
 ...
 requirements(linux + oracle + java6)
 ...
}

我知道上面这段代码相当于

buildType {
 ...
    requirements {
        contains("os.name", "linux")
        equals("db.name", "oracle")
        contains("env.JAVA_HOME", "1.6")
    }
 ...
}

所以我想我的问题可以归结为 'Requirements' 函数的 return 类型是什么,它可以连接在一起?我的猜测是它是某种语句/函数包装器,Kotlin 允许您随时连接它们,函数签名如下所示:

fun Requirements(init: (a: String, b: String) -> UnknownTypeA) : UnknownTypeB

编辑: 对于以后阅读本文时感到困惑的任何人,对 Requirements 的调用实际上是通过 Requirements 构造函数进行的对象初始化。我确实因为没有注意到这一点而不可避免地感到尴尬(名字的大小写应该已经足够提示了!)但是我进行这个编辑是为了让人们清楚它不是一个函数。感谢 Hotkey 指出这一点。

首先,请注意 Requirements 在其构造函数中接受一个函数。在不知道该函数类型的情况下,我们假设它是 Context.() -> Unit (a function with receiver of Context, accepting no arguments and returning Unit).

现在,对于 Requirements 类型,我们自然可以 overload the plus operator,这样它 returns 另一个 Requirements 实例,它的函数可以应用操作数中的两个函数.

您可以通过以下方式在自己的代码中执行此操作:

class Requirements(val check: Context.() -> Unit)

operator fun Requirements.plus(other: Requirements) = 
    Requirements { check(); other.check() }