字段的安装程序通过types投影来删除
我有以下的SSCCE:
class Foo(val bars: Map<Int, Bar>) { fun qux(baz: Baz) { val bar2 = bars[2]!! bar2.bazes += baz } interface Bar { var bazes: MutableList } }
这对我来说似乎很好,但编译器抱怨:
Error:(5, 9) Kotlin: Setter for 'bazes' is removed by type projection
我不知道这意味着什么,更不用说如何纠正它。 这里发生了什么,如何解决这个问题?
有一些小问题。 暂时使用bars[2]!! as Bar
bars[2]!! as Bar
,
w: (4, 20): Unchecked cast: Foo.Bar to Foo.Bar e: (5, 20): Assignment operators ambiguity: public operator fun Collection.plus(element: Baz): List defined in kotlin.collections @InlineOnly public operator inline fun MutableCollection.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' prohibits the use of 'public abstract fun add(element: E): Boolean defined in kotlin.collections.MutableList'
types投影可以安全地做什么的问题。 它得到像对待out Any?
处理out Any?
,所以你可以从列表中读取,但in Nothing
,这意味着你不能添加任何东西到列表中。
从这个例子不清楚你为什么使用*
。 如果不引起任何其他问题,也许你可以拿出
参数,例如
class Foo(val bars: Map>)
问题:你的bars
属性是使用“星形投影”,简单地说就是:“我不知道Bar
的通用types”。 这反过来导致了一个问题:你只能从MutableList
获得某些东西,禁止添加 (因此错误消息:无法使用Setter )。
可能的解决方案:
class Foo(private val bars: Map>) { fun qux(baz: Baz) { val bar2 = bars[2]!! bar2.bazes.add(baz) } interface Bar { var bazes: MutableList } }
我在这里改变的是,我把Foo
打成了in Baz
,这意味着Foo
在其types参数上是逆变的 ,因此Baz
只能被消费。 然后相同的types用于输入参数bars
。 因此,您现在可以将值添加到bars.bazes
,因为关联的MutableList
被认为是Bar
的“消费者”。
btw:不建议使用Baz
作为genericstypes的名称 – 您应该使用更明显的genericstypesT
我知道,这是一个复杂的话题,我真的建议咨询好的文档作为更进一步的步骤:)
plusAssign问题
另一方面+=
( plusAssign
运算符)的用法plusAssign
:编译器抱怨不能选择正确的运算符:
作业运算模糊:
在kotlin.collections中定义了公共运算符fun Collection.plus(element:Any?):List>@InlineOnly public operator inline fun MutableCollection.plusAssign(element:Baz):在kotlin.collections中定义的单位
我试图明确地投给MutableList
,这实际上解决了这个问题。 编译器然后抱怨一个不必要的演员,虽然。 我不知道如何处理这个正确的,除了使用add
而不是诚实的;-)