我想知道在这种特殊情况下如何正确使用in / out方差修饰符。

我有一个具有特定实现类型的通用Map,我想将其分配给更通用的类型下的一个变量:

var generalMap: Map<SimpleExpression<Any>, Any> = emptyMap()
var specificMap: Map<StringExpression, String?> = makeSomeMap()

generalMap = specificMap // this assignment won't compile :(

同样,StringExpression扩展了SimpleExpression<String>。我已经尝试过用out方差修饰符在generalMap定义上进行几种不同的方式:
var generalMap: Map<out SimpleExpression<Any>, out Any?> = emptyMap()

...但不幸的是遇到了相同的编译器错误。

最佳答案

仅当SimpleExpression<T> 仅产生 T值时,才可以进行这种分配。如果是这样,请按照以下说明进行接口(interface)或类的声明:

interface SimpleExpression<out T>

接下来需要更改的是generalMap的声明。将out方差添加到SimpleExpression<..>中,并使Any可为空:
var generalMap: Map<out SimpleExpression<Any>, Any?> = emptyMap()

之后,编译器允许您安全地将specificMap分配给generalMap

如果还生成并使用了T中的SimpleExpression(具有fun consume(t: T)fun produce(): T之类的方法),则应这样声明generalMap:
var generalMap: Map<out SimpleExpression<*>, Any?> = emptyMap()

10-02 02:57