admin管理员组文章数量:1271801
I was told that it could be possible to read a contravariance if used "Any?" as in
fun processList(list: List<in Class1>) {
val item: Any? = list[0]
println(item)
}
To test out, I used:
open class Class2
open class Class1 : Class2()
fun main() {
val list2: List<Class2> =listOf(Class2(), Class2())
val list: List<in Class1> = list2
val item: Any? = list[0]
}
But I doubt this information because I get the error
Projection is conflicting with variance of the corresponding type parameter of 'kotlin.collections.List<in Class1>'. Remove the projection or replace it with '*'.
Is reading not possible at all? Besides, it suggests that I use "*", but why an unbounded wildcard would allow me to read? Shouldn't it have the same restrictions as both covariance and contravariance (not being able to produce nor consume)?
I was told that it could be possible to read a contravariance if used "Any?" as in
fun processList(list: List<in Class1>) {
val item: Any? = list[0]
println(item)
}
To test out, I used:
open class Class2
open class Class1 : Class2()
fun main() {
val list2: List<Class2> =listOf(Class2(), Class2())
val list: List<in Class1> = list2
val item: Any? = list[0]
}
But I doubt this information because I get the error
Projection is conflicting with variance of the corresponding type parameter of 'kotlin.collections.List<in Class1>'. Remove the projection or replace it with '*'.
Is reading not possible at all? Besides, it suggests that I use "*", but why an unbounded wildcard would allow me to read? Shouldn't it have the same restrictions as both covariance and contravariance (not being able to produce nor consume)?
Share Improve this question asked Feb 26 at 9:49 excitedGooseexcitedGoose 1993 bronze badges 1 |1 Answer
Reset to default 3List<in Class1>
itself is simply not a valid type, let alone whether you can read from it.
The type parameter of List
is covariant:
interface List<out E> : Collection<E>
List<in Class1>
contradicts this variance, so is not allowed.
From the language spec,
Kotlin prohibits contradictory combinations of declaration- and use-site variance as follows.
- It is a compile-time error to use a covariant type argument in a contravariant type parameter
- It is a compile-time error to use a contravariant type argument in a covariant type parameter
There is no technical reason for this restriction. This is just to prevent you from doing writing code that doesn't make sense. By using Foo<in T>
, you are expressing that this Foo
should be a consumer of T
, but if the type parameter is covariant at the declaration site, that means Foo
has no way of consuming anything. Clearly, something has gone wrong, and the compiler error is there to tell you that.
If you replace List
with another type with a non-covariant type parameter, it works as expected. You can successfully get a Any?
from a MutableList<in Class1>
for example,
val list2: MutableList<Class2> = mutableListOf(Class2(), Class2())
val list: MutableList<in Class1> = list2
val item: Any? = list[0]
Star projection doesn't have both the restrictions of covariance and contravariance. Such a type would be rather useless, don't you think? It cannot consume anything nor produce anything (regarding its type parameter, at least).
The documentation clearly explains what a star projection means. To paraphrase, if the declaration site variance is invariant, *
acts like out
when you use it as a producer, and acts like in Nothing
when you use it as a consumer. Otherwise, *
will be equivalent to the declaration-site variance.
List
is covariant, so List<*>
just means out Any?
.
版权声明:本文标题:generics - Is there an exception in which it's possible to read a contravariance (in kotlin)? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741139590a2345974.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
List<out E>
, but you try to usein
for the type parameter. Can you clarify why you think this should be able to work? – tyg Commented Feb 26 at 14:38