为什么 Kotlin Map 的键类型参数是不变的?

Lei*_*ter 5 generics collections covariance kotlin

Kotlin 中的接口Map(使用 V1.6.21)的签名为

interface Map<K, out V>
Run Code Online (Sandbox Code Playgroud)

为什么是K不变而不是协变(out K)?

类型参数的文档K说:

映射的键类型是不变的,因为它可以接受键作为参数(例如 containsKey)并在键集中返回它。

但是,接口Set在元素类型中是协变的,因此最后一部分(“在键集中返回它”)不适用,至少不立即适用。

此外,类型参数K仅在未修改映射状态的情况下使用,以用于查找目的(方法containsKey、get、getOrDefault)。在这些地方使用不安全吗@UnsafeVariance?毕竟,相同的技术也被应用于 的Map值类型参数V(例如 中)containsValue,以允许V协变。

hot*_*key 0

我的猜测是,使用 aMap<KSubtype, V>作为 a Map<KSupertype, V>(where KSubtype : KSupertype) 并没有多大意义,因为前者在构造上不能包含除 之外的键的条目KSubtype。

因此,正确的实现应该null从所有对 的调用返回get(kSupertype),并false从那些对 的调用返回containsKey(kSupertype)。

在这种情况下,Set<out E>只有contains函数需要不安全方差,并且Map还需要 上的不安全方差get。与支持用例的价值相比,这可能过于特殊而难以支持。