dictionary - 为什么类 'get' 的 'Map' 方法允许发送不相关的 key 而没有编译错误?

标签 dictionary kotlin compiler-errors

我只是在我的程序中有一个错误,但我根本不明白程序是如何编译的!
我有以下变量:

gamesPerCountriesMap: MutableMap<Long, MutableMap<Long, MutableList<AllScoresGameObj>>>?
我有以下代码行:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem)
正确的行应该是:
var gamesList = gamesPerCountriesMap?.get(countryItem.id)?.get(competitionItem.id)
我查看了 Map 类的原型(prototype),方法声明如下:

public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get(key: K): V?


正如我们所看到的,它可以获得 K 和它的子类型,但是 CompetitionItem 是 CompetitionObj 类的实例,它没有继承 Long 类。
那么为什么编译器没有阻止这个错误呢?我解决了这个问题,但我很清楚什么没有阻止代码被编译?

最佳答案

有两个get Map 的方法界面。
One直接在接口(interface)体中定义:

Map<K, V> { fun get(key: K): V? }
Another (你在你的问题中引用) - 作为一个扩展函数:
fun <K, V> Map<out K, V>.get(key: K): V?
调用的重载决议取决于您是否明确指定泛型参数,以及映射类型 K 之间的关系。泛型参数和传递的类型key争论:
  • 如果你 指定显式泛型参数 ,第二个版本将被调用(如果你写了 .get()<Long, MutableList<AllScoresGameObj>.(competitionItem) ,它不会在你的情况下编译,尽管 .get()<CompetitionObj, MutableList<AllScoresGameObj>.(competitionItem) )会工作,因为在这个 get 里面有不安全的类型转换。重载)。
  • 如果你 省略显式泛型参数 , 作为 key 传递:
  • K 的一个实例类型(或其子类型) - 第一个重载将被称为
  • 其他任何东西 - 第二个重载(导致第一个重载不会编译)。在这种情况下,Kotlin 将尝试推断省略的泛型参数,以便原始映射可以表示为 Map<out inferredK, V>inferredK type 参数是传递的 key 的父类(super class)型争论。最终,它会提出 inferredK = Any .确实 Any是所有事物的父类(super class)型,这样做是完全合法的 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. (我相信在你的情况下,这个警告也应该如此)。为什么这在运行时仍然有效?因为type erasure .


  • 那么,为什么将这个重载版本添加到 stdlib 中呢?
    不确定,也许对于某些法律案件,例如:
    val k : Base = Derived()
    val v = mapOf<Derived, String>().get(k) // will call overloaded variant; will infer K as Base
    
    如果没有这个重载,您将不得不手动回退:
    val v = mapOf<Derived, String>().get(k as Derived) 
    

    关于dictionary - 为什么类 'get' 的 'Map' 方法允许发送不相关的 key 而没有编译错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64936150/

    相关文章:

    json字典类型错误: string indices must be integers

    string - 在 Scala 中替换字符串中的字符

    android - gradlew assembleRelease 失败,出现 java.lang.ClassNotFoundException : com. sun.tools.javac.util.Context

    kotlin - 如何使用 Koin 依赖注入(inject) (Kotlin) 检索与给定类型匹配的所有实例

    c - 我在这里做错了什么?

    haskell - GHCI 中的 Haskell 模板

    iphone - 编译我的应用程序没有错误,但是在设备上编译时挂起

    javascript - 从数组中获取元素直到条件匹配

    javascript - 使用 gmaps.js (谷歌地图 api )

    android - 如何检测应用程序的关闭并采取措施? ( Kotlin )