1

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

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

4

2 回答 2

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>>)
于 2017-08-21T05:28:27.637 回答
1

问题:您的bars财产正在使用“星形投影”,简而言之,这意味着:“我不知道”的通用类型Bar。这反过来又会导致一个问题:您只能从 中获取某些东西MutableList,禁止添加(因此错误消息:No Setter for 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>
    }
}

我在这里改变的是,我用输入了Footyped in Baz,这意味着它的类型参数Foo逆变Baz的,因此s 只能被使用。然后将相同的类型用于输入参数bars。结果,您现在可以值添加到bars.bazes中,因为关联MutableList的据说是Bars 的“消费者”。

顺便说一句:不建议Baz用作泛型类型的名称- 您应该使用更明显的泛型类型。T

我知道,这是一个复杂的话题,我真的建议您参考好的文档作为进一步的步骤:)

plusAssign 问题

+=另一方面, ( operator)的用法plusAssign有点奇怪:编译器抱怨无法选择正确的运算符:

赋值运算符歧义:
public operator fun Collection.plus(element: Any?): List >defined in kotlin.collections

@InlineOnly public operator inline fun MutableCollection.plusAssign(element: Baz):在 kotlin.collections 中定义的单位

我试图明确地bazes转换为MutableList实际上解决了这个问题。然后编译器抱怨一个不必要的转换。老实说,我不知道如何正确处理这个问题,除非使用add;-)

于 2017-08-21T06:12:10.827 回答