如何在kotlin中将通用映射指定为超类

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

我有一个具有特定的实现types的genericsMap ,我想分配给一个更通用的types的variables:

 var generalMap: Map<SimpleExpression, Any> = emptyMap() var specificMap: Map = makeSomeMap() generalMap = specificMap // this assignment won't compile :( 

而且, StringExpression扩展了SimpleExpression 。 我试过在generalMap定义中使用差异修饰符来修改一些不同的方法:

 var generalMap: Map<out SimpleExpression, out Any?> = emptyMap() 

…但不幸的是跑到相同的编译器错误。

只有当SimpleExpression 只产生 T值时,这种赋值才是可能的。 如果是这样,请将您的接口或类声明如下所示:

 interface SimpleExpression 

接下来你必须改变它是generalMap声明。 将方差添加到SimpleExpression<..>并使Any null:

 var generalMap: Map, Any?> = emptyMap() 

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

如果SimpleExpression T被生成和使用(像fun consume(t: T)这样的方法fun consume(t: T)fun produce(): T ),那么你应该像下面这样声明generalMap

 var generalMap: Map, Any?> = emptyMap() 

Map不是关键types的变体,因为它in .get().keys()位置都.keys() 。 把它当作out是不安全的,因为

 var specificMap: Map = makeSomeMap() var generalMap: Map, Any> = specificMap generalMap[intExpression] // specificMap.get(not a StringExpression) 

也就是说,如果您认为这不会导致makeSomeMap()返回的特定Map实现的任何实际问题,那么没有任何东西阻止您进行未经检查的makeSomeMap()