Kotlin和Groovy都提供了一种编写高阶函数的方式,其中函数参数具有隐式接收者。
Kotlin版本
Groovy将其视为带有参数的函数。换句话说,要从Groovy调用Kotlin的
为了让
我想保留这个语法,但避免为我的Kotlin库定义的每个高阶函数编写额外的样板重载。有没有更好(更无缝/自动化)的方法可以让Groovy使用Kotlin的带接收者函数语法,以便我不必手动为每个Kotlin函数添加样板重载?我的玩具示例的完整代码和编译说明在gitlab上。
class KotlinReceiver {
fun hello() {
println("Hello from Kotlin")
}
}
class KotlinVersion {
fun withReceiver(fn: KotlinReceiver.() -> Unit) {
KotlinReceiver().fn()
}
}
// And then I can call...
val foo = KotlinVersion()
foo.withReceiver { hello() }
Groovy 版本
class GroovyReceiver {
void hello() {
println("Hello from Groovy")
}
}
class GroovyVersion {
void withReceiver(Closure fn) {
fn.resolveStrategy = Closure.DELEGATE_FIRST
fn.delegate = new GroovyReceiver()
fn.run()
}
}
// And then I can call...
def foo = new GroovyVersion()
foo.withReceiver { hello() }
我的目标是在Kotlin中编写withReceiver
函数,但从Groovy调用它并使{ hello() }
正常工作。然而,如此编写的话,Kotlin会生成类似下面的字节码:
public final void withReceiver(@NotNull Function1 fn) { /* ... */ }
Groovy将其视为带有参数的函数。换句话说,要从Groovy调用Kotlin的
withReceiver
,我必须这样做:(new KotlinVersion()).withReceiver { it -> it.hello() }
为了让
{ hello() }
不需要 it -> it.
,我需要添加一个重载函数,该函数以 groovy.lang.Closure
作为参数。
Kotlin 版本
import groovy.lang.Closure
class KotlinVersion {
fun withReceiver(fn: KotlinReceiver.() -> Unit) {
KotlinReceiver().fn()
}
fun withReceiver(fn: Closure<Any>) = withReceiver {
fn.delegate = this
fn.resolveStrategy = Closure.DELEGATE_FIRST
fn.run()
}
}
有了这种超载,给定一个名为foo
的KotlinVersion
实例,以下行在两种语言中都可以正常工作:
// If this line appears in Groovy code, it calls the Closure overload.
// If it's in Kotlin, it calls the KotlinReceiver.() -> Unit overload.
foo.withReceiver { hello() }
我想保留这个语法,但避免为我的Kotlin库定义的每个高阶函数编写额外的样板重载。有没有更好(更无缝/自动化)的方法可以让Groovy使用Kotlin的带接收者函数语法,以便我不必手动为每个Kotlin函数添加样板重载?我的玩具示例的完整代码和编译说明在gitlab上。
public final void withKotlinReceiver(groovy.lang.Closure fn) { /* ... */ }
? - daggettbuildSrc
文件夹中,我正在尝试使其可从用 Groovy 编写的 gradle 脚本中调用。我已经检查了玩具示例,并提供了编译说明,放到了 GitLab 上。 - Dan