本文介绍了Kotlin认为两个方法具有相同的JVM签名,但实际上没有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自C#背景,我知道如何在C#中实现这一点,但是我在Kotlin方面苦苦挣扎.我有2个扩展功能:

I came from the C# background and I know how to implement this in C#, but I'm struggling with Kotlin.I've got 2 extension functions:

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

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

很明显,func的返回类型在两个函数中都不同.第一个函数执行它并返回它,第二个函数执行func并返回func的结果.但这给了我一个错误:

Clearly, the return type of func is different in both functions. The first function executes it and returns this, the second executes func and returns the result of func.But it gives me an error:

平台声明冲突:以下声明具有相同的JVM签名".

"Platform declaration clash: The following declarations have the same JVM signature".

如何在Kotlin中正确实现此目的?

How to implement this correctly in Kotlin?

推荐答案

在JVM上,我们必须应对类型擦除的问题.从本质上讲,这意味着类型(在这种情况下为T)在已编译的字节码中被丢弃,并且所需的检查仅在编译时进行.鉴于此,您必须牢记这一点.

On the JVM, we have to contend with type erasure. Meaning essentially that the types (T in this case) are thrown away in the compiled bytecode and that required checks are only done at compile time. Given that, you have to look at your function declaration with that in mind.

在两种情况下,Kotlin都会将您的函数参数定义为Function0.由于类型被删除,因此() -> Unit() -> Foo<T>在字节码中看起来都相同.我们可以通过反编译您提供的代码来证明这一点(我重命名了这些myFunction2中的一个以使其正常工作):

Kotlin will define your function argument as a Function0 in both cases. Because the types are erased, () -> Unit and () -> Foo<T> both look the same in the bytecode. We can prove this out by decompiling the code you've provided (I renamed one of these myFunction2 to get this to work):

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不能区分这些功能的类型.

This is what the Kotlin compiler is generating (it does more, but I have removed the non-essential parts from this example). As you can see, our types are gone thanks to type erasure. And if we undo my change (myFunction2 becomes myFunction), there's no way at all to tell these apart. This is what the compiler is complaining about - if you erase the types the JVM can't tell these functions apart.

这篇关于Kotlin认为两个方法具有相同的JVM签名,但实际上没有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

查看更多