[英]Why does 'get' method of class 'Map' enable sending a not relevant key without a compilation error?
我只是在我的程序中有一個錯誤,但我根本不明白該程序是如何編譯的!
我有以下變量:
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 類的原型,該方法聲明如下:
公共內聯運算符 fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get(key: K): V?
正如我們所看到的,它可以獲取 K 並且它是子類型,但是作為 CompetitionObj 類的 instacne 的競爭項並沒有繼承Long類。 那么為什么編譯器沒有阻止這個錯誤呢? 我解決了這個問題,但我很清楚什么沒有阻止代碼被編譯?
Map
接口有兩種get
方法。
一種是直接在接口主體中定義的:
Map<K, V> { fun get(key: K): V? }
另一個(您在問題中引用) - 作為擴展函數:
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
類型(或其子類型)的實例 - 第一個重載將被調用Map<out inferredK, V>
並且inferredK
類型參數是傳遞的key
參數的超類型。 最終,它會得到inferredK
= Any
。 事實上Any
是所有事物的超類型,對任何K
執行val x: Map<out Any, V> = mapOf<K, V>()
是完全合法的。 實際上編譯器意識到這是一個微不足道的解決方案並發出編譯警告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 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
如果沒有這個重載,你就必須手動轉換:
val v = mapOf<Derived, String>().get(k as Derived)
為什么有兩個get
方法?
val x: kotlin.collections.List<String>= java.util.ArrayList<>()
擁有
open class A
class B
在 Java 中是非法的
List<A> x = new ArrayList<B>();
但在 Kotlin 中絕對正常
val x: List<A> = ArrayList<B>()
至於我期望的Map
示例
錯誤:類型推斷失敗。 類型參數 K 的值應在輸入類型(參數類型、接收器類型或預期類型)中提及。 嘗試明確指定它
自 Kotlin 1.0.0 起類型推斷被破壞時
如果真的有問題,很高興看到您正在使用的代碼粘貼和 kotlin 編譯器版本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.