I have the following 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>
}
}
This seems fine to me, but the compiler complains that:
Error:(5, 9) Kotlin: Setter for 'bazes' is removed by type projection
I have no idea what this even means, much less how to correct it. What's going on here and how do I get around it?
The issue: Your bars
property is using "star projection", which, put simply, just means: "I don't know the generic type of Bar
". This in turn leads to a problem: You'll only be able to get something from the MutableList
, adding is prohibited (Thus the error message: No Setter for bazes
!).
A possible solution:
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>
}
}
What I changed here, is that I made Foo
typed with in Baz
, which means Foo
is made contravariant in its type parameter, thus Baz
s can only be consumed. The same type is then used for the input parameter bars
. As a result, you're now able to add values into bars.bazes
, because the associated MutableList
is said to be a "Consumer" of Bar
s.
btw: Using Baz
as a name for the generic type isn't recommended - You should rather use T
which is more obvious to be a generic type.
I know, it's a complex topic and I really advise to consult the good documentation as a further step :)
The plusAssign issue
The usage of +=
(plusAssign
operator) on the other hand is a bit weird:
The compiler complains not to be able to choose the correct operator:
Assignment operators ambiguity:
public operator fun Collection.plus(element: Any?): List >defined in kotlin.collections@InlineOnly public operator inline fun MutableCollection.plusAssign(element: Baz): Unit defined in kotlin.collections
I tried to explicitly cast bazes
to MutableList
which in fact solves the issue. The compiler then complains about an unecessary cast though. I don't know how to handle this properly to be honest except using add
instead ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With