我在kotlin安全通话中遇到过载分辨率模糊错误

Al *_*mun 12 nullable kotlin

我有一个可以为空的字符串变量ab.如果我toUpperCase在为其分配null后通过安全调用操作符调用,则kotlin会给出错误.

fun main(args: Array<String>){
    var ab:String? = "hello"
    ab = null
    println(ab?.toUpperCase())
}
Run Code Online (Sandbox Code Playgroud)

错误:( 6,16 )
重载分辨率歧义:
@InlineOnly public inline fun Char.toUpperCase():在kotlin.text中定义的char
@InlineOnly public inline fun String.toUpperCase():在kotlin.text中定义的字符串

这有什么问题?

Bak*_*aii 6

正如本文档中关于智能模型所述:

x = y使赋值后的y类型为x

该生产线ab = null大概智能蒙上abNothing?.如果你检查ab is Nothing?它确实true.

var ab: String? = "hello"
ab = null
println(ab?.toUpperCase())
println(ab is Nothing?) // true
Run Code Online (Sandbox Code Playgroud)

由于Nothing?是所有类型的子类型(包括Char?String?),它解释了为什么会出现Overload resolution ambiguity错误.这个错误的解决方案将是Willi Mentzel在他的回答中提到ab的,String在调用之前转换为类型toUpperCase().


备注:当类实现两个接口并且两个接口都具有相同签名的扩展函数时,将发生此类错误:

//interface
interface A {}
interface B {}

//extension function
fun A.x() = 0
fun B.x() = 0

//implementing class
class C : A, B {}

C().x()    //Overload resolution ambiguity
(C() as A).x()    //OK. Call A.x()
(C() as B).x()    //OK. Call B.x()
Run Code Online (Sandbox Code Playgroud)

  • 等等,第一行不是已经将 `ab` 定义为 Nullable String 了吗?那么为什么要强制转换为 String 呢?有必要吗? (2认同)

s1m*_*nw1 3

我不确定,但这似乎是由于智能转换(Nothing?每个可为空类型的子类型)而导致的错误。这个有效:

fun main(args: Array<String>) {
    var ab: String? = "hello"
    ab = makeNull()
    println(ab?.toUpperCase())
}

fun makeNull(): String? = null
Run Code Online (Sandbox Code Playgroud)

唯一的区别:编译器不null直接知道赋值,这似乎导致了您的示例中的错误。但尽管如此,你的应该也能工作。