Eit*_*s30 6 dictionary compiler-errors kotlin
我只是在我的程序中有一个错误,但我根本不明白该程序是如何编译的!
我有以下变量:
gamesPerCountriesMap: MutableMap<Long, MutableMap<Long, MutableList<AllScoresGameObj>>>?
Run Code Online (Sandbox Code Playgroud)
我有以下代码行:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem)
Run Code Online (Sandbox Code Playgroud)
正确的行应该是:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem.id)
Run Code Online (Sandbox Code Playgroud)
我查看了 Map 类的原型,该方法声明如下:
公共内联运算符 fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get(key: K): V?
正如我们所看到的,它可以获取 K 并且它是子类型,但是作为 CompetitionObj 类的 instacne 的竞争项并没有继承Long类。那么为什么编译器没有阻止这个错误呢?我解决了这个问题,但我很清楚什么没有阻止代码被编译?
接口有两种get
方法Map
。
一种是直接在接口主体中定义:
Map<K, V> { fun get(key: K): V? }
Run Code Online (Sandbox Code Playgroud)
另一个(您在问题中引用的)- 作为扩展函数:
fun <K, V> Map<out K, V>.get(key: K): V?
Run Code Online (Sandbox Code Playgroud)
调用时的重载决策取决于您是否显式指定泛型参数,以及映射K
泛型参数类型与传递参数类型之间的关系key
:
.get()<Long, MutableList<AllScoresGameObj>.(competitionItem)
,尽管.get()<CompetitionObj, MutableList<AllScoresGameObj>.(competitionItem)
)会起作用,因为此get
重载内存在不安全的强制转换)。key
:
K
- 将调用第一个重载Map<out inferredK, V>
并且inferredK
类型参数是传递参数的超类型key
。最终,它会得出inferredK
= Any
。IndeedAny
是所有事物的超类型,对val x: Map<out Any, V> = mapOf<K, V>()
任何K
. 实际上编译器意识到这是一个微不足道的解决方案并发出编译警告Type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
(我相信在你的情况下这个警告也应该是)。为什么这在运行时仍然有效?因为类型擦除。那么,为什么这个重载版本会被添加到 stdlib 中呢?不确定,也许对于一些法律案件,例如:
val k : Base = Derived()
val v = mapOf<Derived, String>().get(k) // will call overloaded variant; will infer K as Base
Run Code Online (Sandbox Code Playgroud)
如果没有这个重载,你就必须手动强制转换:
val v = mapOf<Derived, String>().get(k as Derived)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
243 次 |
最近记录: |