Kotlin 混合泛型和重定义方法,给出不同的返回类型,哪些可以编译?

Kotlin 混合泛型和重定义方法,给出不同的返回类型,哪些可以编译?,kotlin,Kotlin,Kotlin编译器不允许重定义函数,例如: fun tmp() = 1 fun tmp() = "" 而且基于JVM的语言具有通用擦除功能,因此无法编译以下代码 class Test<T>(a: T) fun Test<String>.myFun() = Test(1) fun Test<Int>.myFun() = Test("") 类测试(a:T) fun Test.myFun()=测试(1) fun Test.myFun()=Test(“”) 但

Kotlin编译器不允许重定义函数,例如:

fun tmp() = 1
fun tmp() = "" 
而且基于JVM的语言具有通用擦除功能,因此无法编译以下代码

class Test<T>(a: T)
fun Test<String>.myFun() = Test(1)
fun Test<Int>.myFun() = Test("")
类测试(a:T)
fun Test.myFun()=测试(1)
fun Test.myFun()=Test(“”)
但是这个呢,为什么可以编译呢

class Test<T>
fun Test<String>.myFun() = 1
fun Test<Int>.myFun() = ""
类测试
fun Test.myFun()=1
乐趣测试。myFun()=“”

由于通用擦除,这两个函数的参数相同,只是返回类型不同。由于第一个示例的原因,不应编译此文件。为什么可以编译它?

在第一个示例中,您没有尝试重新定义函数。您正在尝试定义两个单独的函数。虽然它们的签名不同,但它们还有另一个问题:冲突重载。编译器将无法区分您调用的是哪一个,因为输入参数完全相同

class Test<T>
fun Test<String>.myFun() = 1
fun Test<Int>.myFun() = ""
在第二个示例中,问题是匹配签名,而不是冲突重载

最后一个示例没有问题,因为您没有匹配的签名或冲突的重载。使用它们时,编译器可以区分使用泛型类型调用的是哪一个。这发生在类型擦除之前,所以这不是问题

在Java世界中,术语“方法签名”被重载可能会引起一些混淆。当谈到您编写的代码和编译器可以处理的内容时,返回类型不是签名的一部分。但是在字节码和JVM记录的错误中,返回类型是签名的一部分。如果您尝试用Java编写第三个示例,它会抱怨方法具有相同的擦除功能。我不知道这项限制的细节,但科特林在这里更为宽大