我想知道在这种特殊情况下如何正确使用输入/输出方差修饰符。
我有一个具有特定实现类型的通用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()
...但遗憾的是遇到了相同的编译错误。
答案 0 :(得分:2)
Map
不是密钥类型的变体,因为它位于in
位置.get()
和out
位置.keys()
。将其视为out
并不安全,因为
var specificMap: Map<StringExpression, String?> = makeSomeMap()
var generalMap: Map<SimpleExpression<Any>, Any> = specificMap
generalMap[intExpression] // specificMap.get(not a StringExpression)
话虽如此,如果您认为这不会导致Map
返回的特定makeSomeMap()
实现出现任何实际问题,则无法阻止您进行未经检查的演员。
答案 1 :(得分:2)
只有在SimpleExpression<T>
仅生成 T值时才可以进行此类分配。如果是这样,请按以下方式进行界面或类声明:
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()