我有以下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>
}
}
这对我来说似乎很好,但编译器抱怨说:
Error:(5, 9) Kotlin: Setter for 'bazes' is removed by type projection
我不知道这甚至意味着什么,更不用说如何纠正它。这里发生了什么,我该如何解决它?
答案 0 :(得分:1)
有几个小问题。暂时使用bars[2]!! as Bar<Baz>
,
w: (4, 20): Unchecked cast: Foo.Bar<Any?> to Foo.Bar<Baz>
e: (5, 20): Assignment operators ambiguity:
public operator fun <T> Collection<Baz>.plus(element: Baz): List<Baz> defined in kotlin.collections
@InlineOnly public operator inline fun <T> MutableCollection<in Baz>.plusAssign(element: Baz): Unit defined in kotlin.collections
Kotlin不知道是以bar2.bazes = bar2.bazes.plus(baz)
还是bar2.bazes.plusAssign(baz)
来处理它。如果您将其更改为var2.bazes.add(baz)
或val bazes
,则歧义会消失。
解决这个问题并删除不安全的演员阵容
e: (5, 20): Out-projected type 'MutableList<out Any?>' prohibits the use of 'public abstract fun add(element: E): Boolean defined in kotlin.collections.MutableList'
关于类型投影可以安全地做什么的问题。它被视为out Any?
,因此您可以从列表中读取,但in Nothing
,这意味着您无法向列表中添加任何内容。
从这个例子中不清楚为什么你使用*
。如果它没有引起任何其他问题,也许你可以取出<Baz>
参数,例如
class Foo<Baz>(val bars: Map<Int, Bar<Baz>>)
答案 1 :(得分:1)
问题:您的bars
媒体资源正在使用&#34;星级投影&#34;,简而言之,只是意味着:&#34;我不会知道Bar
&#34;的通用类型。这又会导致一个问题:您只能 来自MutableList
,添加是禁止的(因此错误消息: bazes
没有 Setter !)。
可能的解决方案:
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>
}
}
我在此处更改的是,我使用Foo
键入了in Baz
,这意味着Foo
在其类型参数中被设为逆变,因此{{ 1}}只能被消费。然后将相同的类型用于输入参数Baz
。因此,您现在能够将值添加到bars
,因为关联的bars.bazes
被认为是&#34;消费者&#34; MutableList
s。
btw:使用Bar
作为通用类型的名称isn&#39; t recommended - 您应该使用Baz
,这更明显是通用类型。
我知道,这是一个复杂的话题,我真的建议再去咨询好documentation :)
plusAssign问题
另一方面,T
(+=
运算符)的使用有点奇怪:
编译器抱怨无法选择正确的运算符:
分配操作员歧义:
public operator fun Collection.plus(element:Any?):List&gt;在kotlin.collections中定义@InlineOnly公共运营商内联乐趣 MutableCollection.plusAssign(element:Baz):单位 在kotlin.collections中定义
我尝试明确地将plusAssign
投射到bazes
,这实际上解决了这个问题。然后,编译器会抱怨不必要的强制转换。除了使用MutableList
之外,我不知道如何正确处理这个问题; - )