带接收器的Kotlin函数参数,从Groovy调用

带接收器的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(

Kotlin和Groovy都提供了一种编写高阶函数的方法,其中函数参数具有隐式接收器

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()
    }
}
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脚本中调用。我已经检查了玩具示例,以及编译说明,