Kotlin中的Map
接口(使用V1.6.21)有一个签名
interface Map<K, out V>
为什么K
不变而不是协变(out K
)?
类型参数K
的文档说:
map的键类型是不变的,因为它可以接受key作为参数(例如containsKey),并在keys set中返回它。
但是,接口Set
在元素类型中是协变的,因此最后一部分("在keys set"中返回它")不适用,至少不是立即适用。
此外,类型参数K
仅在未修改映射状态的情况下使用,用于查找目的(方法containsKey
,get
,getOrDefault
)。在这些地方,使用@UnsafeVariance
不是很安全吗?毕竟,Map
的值类型参数V
也采用了同样的技术,例如在containsValue
中,允许V
协变。
我的猜测是,使用Map<KSubtype, V>
作为Map<KSupertype, V>
(其中KSubtype : KSupertype
)并没有多大意义,因为前者根据构造不能包含除KSubtype
以外的键项。
所以一个正确的实现应该从所有对get(kSupertype)
的调用中返回null
,从那些对containsKey(kSupertype)
的调用中返回false
。
在Set<out E>
的情况下,只有contains
函数需要不安全方差,Map
也需要get
的不安全方差。与支持用例的价值相比,这可能是太多的特性来支持了。