带接收器的Kotlin函数参数,从Groovy调用
Kotlin和Groovy都提供了一种编写高阶函数的方法,其中函数参数具有隐式接收器 Kotlin版本带接收器的Kotlin函数参数,从Groovy调用,groovy,kotlin,kotlin-interop,Groovy,Kotlin,Kotlin Interop,Kotlin和Groovy都提供了一种编写高阶函数的方法,其中函数参数具有隐式接收器 Kotlin版本 class KotlinReceiver { fun hello() { println("Hello from Kotlin") } } class KotlinVersion { fun withReceiver(fn: KotlinReceiver.() -> Unit) { KotlinReceiver().fn(
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() }
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() }
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()
}
}
Groovy版本
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() }
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() }
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()
}
}
我的目标是在Kotlin中编写withReceiver
函数,但从groovy调用它并使{hello()}
工作。不过,正如所写,Kotlin生成的字节码类似于
public final void withReceiver(@NotNull Function1 fn) { /* ... */ }
Groovy将其视为带参数的函数。换句话说,要从Groovy调用Kotlin的with receiver
,我必须这样做:
(new KotlinVersion()).withReceiver { it -> it.hello() }
为了允许{hello()}
不使用it->it.
,我必须添加一个重载,将groovy.lang.Closure
作为其参数
Kotlin版本
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() }
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() }
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()
}
}
我试图保持这种语法,但避免为Kotlin库定义的每个高阶函数编写额外的模板重载。有没有更好(更无缝/自动)的方法使Kotlin函数的接收器语法可以从Groovy中使用,这样我就不必手动向我的每个Kotlin函数添加样板文件重载
上面我的玩具示例的完整代码和编译说明如下。在groovy中,您可以动态定义新函数
KotlinVersion.metaClass.withReceiver = { Closure c->
delegate.with(c)
}
这将为类KotlinVersion
并允许使用此语法来KotlinVersion
实例:
kv.withReceiver{ toString() }
在这种情况下,将在kv
您可以编写函数,使用
kotlin.function
参数迭代kotlin类的已声明方法,并通过元类使用groovy.lang.Closure
参数声明新方法 限制在哪里?为什么不能创建字节码形式的kotlin代码:public final void with kotlin receiver(groovy.lang.Closure fn){/*…*/}
?@daggett我的变通方法中的kotlin示例正是这样做的,我只是试图避免为库中的每个高阶函数手工编写这样的包装器。我想可能有Groovy magic和/或Kotlin编译器属性的一些组合可以实现相同的语法,而无需大量手工编写的样板文件。请提供更多详细信息,说明您如何看待Groovy脚本/类以及它如何导入Kotlin..我不确定您在问什么,因此,我编辑了这个问题,试图让它更清楚地说明我想要实现的目标。上下文是我的Kotlin代码位于buildSrc
文件夹中,我正试图使它可以从Groovy编写的gradle脚本中调用。我已经检查了玩具示例,以及编译说明,