Generics 字段的Setter通过类型投影移除

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> } } 我甚至不知道

我有以下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>
    }
}

我甚至不知道这意味着什么,更不用说如何纠正了。这里发生了什么?我该如何应对?

有几个小问题。临时使用
条[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(值条:映射)

问题是:您的
属性使用了“星投影”,简单地说,它的意思是:“我不知道
的通用类型。”。这反过来又导致了一个问题:您只能从
可变列表
中获取某些内容,添加是被禁止的(因此错误消息:NoSetterfor
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>
    }
}
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>
    }
}