Kotlin认为两个方法具有相同的JVM签名,但实际上不是

lsmepo6l  于 2023-10-23  发布在  Kotlin
关注(0)|答案(3)|浏览(162)

我来自C#背景,我知道如何在C#中实现这一点,但我正在努力使用Kotlin。我有两个扩展函数:

fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T>

fun <T> Foo<T>.myFunction(func: () -> Foo<T>): Foo<T>

显然,func的返回类型在两个函数中是不同的。第一个函数执行它并返回this,第二个函数执行func并返回func的结果。但它给了我一个错误:
“平台宣言冲突:以下声明具有相同的JVM签名”“。
如何在Kotlin中正确实现这一点?

0aydgbwb

0aydgbwb1#

由于类型擦除(* 内部 * Function0<T> * 类用于表示函数参数 *),您的函数在JVM中具有冲突的签名;你可以通过给它们每个一个JVM特定的名字来解决这个问题。在Kotlin中,你仍然可以用原来的名字访问它们,但是在Java或内部,实际上使用了另一个名字。只需在替代版本上使用@JvmName注解:

fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T>

@JvmName("myfunctionWithFoo")   
fun <T> Foo<T>.myFunction(func: () -> Foo<T>): Foo<T>
rqdpfwrv

rqdpfwrv2#

在JVM上,我们必须使用contend with type erasure。本质上意味着类型(在本例中为T)在编译后的字节码中被丢弃,并且所需的检查仅在编译时完成。考虑到这一点,你必须考虑到这一点来看待你的函数声明。
在这两种情况下,Kotlin都会将函数参数定义为Function0。因为类型被擦除,所以() -> Unit() -> Foo<T>在字节码中看起来是一样的。我们可以通过反编译您提供的代码来证明这一点(我将其中一个重命名为myFunction2以使其工作):

public final class com/ginsberg/KotlinStuffKt {
    public final static myFunction(Lcom/ginsberg/Foo;Lkotlin/jvm/functions/Function0;)Lcom/ginsberg/Foo;

    public final static myFunction2(Lcom/ginsberg/Foo;Lkotlin/jvm/functions/Function0;)Lcom/ginsberg/Foo;

}

这就是Kotlin编译器正在生成的内容(它做的更多,但我已经从这个例子中删除了不必要的部分)。正如你所看到的,由于类型擦除,我们的类型消失了。如果我们撤销我的更改(myFunction2变成myFunction),就根本没有办法区分它们。这就是编译器所抱怨的--如果你删除了JVM无法区分这些函数的类型。

cclgggtu

cclgggtu3#

1.请更改您的fragmentManager名称,因为您的参数作为fragmentManager,它将与基类参数名称(默认情况下也是fragmentManager)反转。因此,更改参数的名称将对您有所帮助。

from: 
 private val fragmentManager: FragmentManager? = null
 private val context: Context? = null

to:
 private val fragmentManagerNowPlaying: FragmentManager? = null
 private val contextNowPlaying: Context? = null

相关问题