Generics 字段的Setter通过类型投影移除
我有以下SSCCE:Generics 字段的Setter通过类型投影移除,generics,kotlin,erasure,Generics,Kotlin,Erasure,我有以下SSCCE: class Foo(val bars: Map<Int, Bar<*>>) { fun <Baz> qux(baz: Baz) { val bar2 = bars[2]!! bar2.bazes += baz } interface Bar<Baz> { var bazes: MutableList<Baz> } } 我甚至不知道
class Foo(val bars: Map<Int, Bar<*>>) {
fun <Baz> qux(baz: Baz) {
val bar2 = bars[2]!!
bar2.bazes += baz
}
interface Bar<Baz> {
var bazes: MutableList<Baz>
}
}
我甚至不知道这意味着什么,更不用说如何纠正了。这里发生了什么?我该如何应对?有几个小问题。临时使用
条[2]!!作为条形码
w:(4,20):未选中的强制转换:Foo.Bar到Foo.Bar
e:(5,20):赋值运算符歧义:
public operator fun Collection.plus(元素:Baz):在kotlin.collections中定义的列表
@InlineOnly公共运算符inline fun MutableCollection.plusSign(元素:Baz):在kotlin.collections中定义的单位
Kotlin不知道是否将其处理为bar2.bazes=bar2.bazes.plus(baz)
或bar2.bazes.plusAssign(baz)
。如果将其更改为var2.bazes.add(baz)
或valbazes
则歧义消失
修复并移除不安全的石膏会导致
e:(5,20):Out投影类型“MutableList”禁止使用“public abstract fun add(element:e):kotlin.collections.MutableList中定义的布尔值”
使用类型投影可以安全地执行哪些操作的问题。它被视为out Any?
,因此您可以从列表中读取,但不包含任何内容
,这意味着您无法向列表中添加任何内容
从这个例子中不清楚为什么要使用*
。如果它没有引起任何其他问题,也许您可以取消
参数,例如
class Foo(值条:映射)
问题是:您的条
属性使用了“星投影”,简单地说,它的意思是:“我不知道条
的通用类型。”。这反过来又导致了一个问题:您只能从可变列表
中获取某些内容,添加是被禁止的(因此错误消息:NoSetterforbazes
!)
可能的解决方案:
class Foo<in Baz>(private val bars: Map<Int, Bar<in Baz>>) {
fun qux(baz: Baz) {
val bar2 = bars[2]!!
bar2.bazes.add(baz)
}
interface Bar<Baz> {
var bazes: MutableList<Baz>
}
}
class Foo(专用val条:地图){
乐团(baz:baz){
val bar2=条[2]!!
bar2.bazes.add(baz)
}
接口条{
var bazes:可变列表
}
}
我在这里更改的是,我在Baz中使用键入Foo
,这意味着Foo
在其类型参数中是逆变的,因此只能使用Baz
s。然后,相同类型用于输入参数条
。因此,您现在可以将值添加到Bar.bazes
,因为关联的MutableList
被称为Bar
的“消费者”
顺便说一句:使用Baz
作为泛型类型的名称不是-您应该使用t
,这对于泛型类型来说更为明显
我知道,这是一个复杂的话题,我真的建议进一步咨询好的方面:)
plusaSign问题
另一方面,+=
(plusAssign
操作符)的用法有点奇怪:
编译器抱怨无法选择正确的运算符:
赋值运算符歧义:
在kotlin.collections中定义的公共操作符fun Collection.plus(元素:Any?):List>
@InlineOnly公共运营商在线娱乐
可变集合.plusAssign(元素:Baz):单位
在kotlin.collections中定义
我试图显式地将bazes
转换为MutableList
,这实际上解决了这个问题。然后,编译器抱怨不必要的强制转换。老实说,我不知道如何正确处理这个问题,除了使用add
代替;-) 条[2]
正在检索一个条形图
,这使得条形图
成为一个可变列表
,因此您根本无法添加/设置该列表,因为您不知道实际的类型参数。请记住,函数的泛型类型参数是不相关的,可以是任何类型。至于为什么错误消息如此隐晦,我不知道……但这肯定不应该编译。正如我提到的,使用声明val bazes
而不是var bazes
,没有歧义,编译器总是解析为.plusAssign()
。然后您应该使用add imhoI did。“如果将其更改为var2.bazes.add(baz)
或val bazes
则歧义消失。”
class Foo<in Baz>(private val bars: Map<Int, Bar<in Baz>>) {
fun qux(baz: Baz) {
val bar2 = bars[2]!!
bar2.bazes.add(baz)
}
interface Bar<Baz> {
var bazes: MutableList<Baz>
}
}