提问人:Al Mamun 提问时间:12/19/2017 最后编辑:BakaWaiiAl Mamun 更新时间:12/20/2017 访问量:5619
我在 kotlin 安全调用时出现过载解析模糊错误
I'm getting Overload resolution ambiguity error on kotlin safe call
问:
我有一个可以为空的字符串变量。如果我在为其分配 null 后通过安全呼叫操作员进行调用,则 kotlin 会出错。ab
toUpperCase
fun main(args: Array<String>){
var ab:String? = "hello"
ab = null
println(ab?.toUpperCase())
}
错误:(6, 16)
过载解析歧义:
@InlineOnly public 内联乐趣 Char.toUpperCase(): 在 kotlin.text 中定义的字符 @InlineOnly 公共内联乐趣 String.toUpperCase(): 在 kotlin.text
中定义的字符串
这里有什么问题?
答:
我不确定,但由于智能转换(到,每个可为空类型的子类型),这似乎是一个错误。这个有效:Nothing?
fun main(args: Array<String>) {
var ab: String? = "hello"
ab = makeNull()
println(ab?.toUpperCase())
}
fun makeNull(): String? = null
唯一的区别是:编译器不直接知道赋值,这似乎会导致示例中的错误。但是,你的可能也应该有效。null
这似乎真的是一个错误。该类型在赋值时以某种方式丢失,因此您必须明确地告诉编译器它应该处理 .String?
null
String?
fun main(args: Array<String>){
var ab: String? = "hello"
ab = null
println((ab as String?)?.toUpperCase()) // explicit cast
// ...or
println(ab?.let { it.toUpperCase() }) // use let
}
我相信这是由于 Kotlin 使用的智能转换。换句话说,Kotlin 能够在以下代码行之后推断出这一点:
ab = null
变量的类型很简单(这不是您可以在 Kotlin 中使用的实际类型 - 我只是指的是允许值的范围),而不是(换句话说,没有办法包含 )。ab
null
String?
ab
String
考虑到 toUpperString() 扩展函数只为 Char 和 String(而不是 Char? 或 String?)定义,因此无法在它们之间进行选择。
为了避免这种行为,请参阅其他人提出的答案(例如,显式转换为 String?),但这绝对看起来像一个功能(并且非常有用),而不是对我来说是一个错误。
评论
null
null
null
toUpperCase()
如本文档中关于智能投射的说明:
x = y 使赋值后 y 类型的 x
这条线可能聪明地转换为 .如果你检查它确实是.ab = null
ab
Nothing?
ab is Nothing?
true
var ab: String? = "hello"
ab = null
println(ab?.toUpperCase())
println(ab is Nothing?) // true
由于是所有类型(包括 和)的子类型,因此它解释了出现错误的原因。此错误的解决方案将是 Willi Mentzel 在他的回答中提到的,在调用之前转换为类型。Nothing?
Char?
String?
Overload resolution ambiguity
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()
评论
ab
ab
Nothing?
Nothing?
String?
Char?
toUpperCase()
String
Char
String
ab is Nothing?
null
我反编译了你的函数,我想:在你制作编译器的那一刻之后,它会智能地转换它,把每一个 .然后 as 没有类型。您无法推断 的接收方的类型。ab = null
null
(ACONST_NULL)
ab
null
toUpperCase()
这是从 kotlin 字节码生成的 java 等效代码:
public final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
String ab = "hello";
ab = (String)null;
Object var3 = null;
System.out.println(var3);
}
这看起来是一个应该由 kotlin 团队解决的问题。
评论
toInt
toUpperCase
评论