Recently I ran into a problem where I had a function which had to return an Array of I
s, in form of all values of enum E
, with E
implementing interface I
, with every code that came to my mind compiler complained about type mismatch:
Error:(x, x) Kotlin: Type mismatch: inferred type is Array<E> but Array<I> was expected
A minimal example:
interface I {}
enum class E: I {
A, B, C;
}
fun getMoreInterfaces(): Array<I> {
return E.values()
}
This happens when trying to assign E.values()
to variable of type Array<I>
I am positive that this should be possible since E
implements I
.
Another thing that I came up while testing is that it works just fine when used like this:
interface I {}
enum class E: I {
A, B, C;
}
fun getMoreInterfaces(): Array<I> {
return arrayOf(E.A, E.B, E.C)
}
I did a lot of searching on this topic but with no luck (perhaps I chose the wrong way to describe it?)
In Kotlin, unlike Java, Array<T>
is invariant on T
, so, for E
that is a subtype of I
, Array<E>
and Array<I>
are not subtypes of each other. See: Variance .
Given that the Array<T>
types also store the item type and cannot be subject to fully unchecked casts , your best way to solve this is to create a separate array.
You can do that by either creating an array manually and filling it with the items, like in your example (or by using the constructor Array(n) { ... }
), or use .toTypedArray()
applied to the list representation of the array ( .asList()
):
fun getMoreInterfaces(): Array<I> {
return E.values().asList().toTypedArray()
}
But basically, you can just go with a List<I>
if you are not in performance-critical code, which is more idiomatic for Kotlin than working with arrays, and also simpler.
Array
is an invariant generic type in Kotlin, so if you need to return an instance of Array<I>
, you can't return Array<E>
instead, even if E
is a subtype of I
.
But in case if you are only consuming values from the returned array, you can declare its type as Array<out I>
. This type is a covariant projection of type Array<I>
and it allows you to return both Array<I>
and Array<E>
.
interface I {}
enum class E: I {
A, B, C
}
fun getMoreInterfaces(): Array<out I> {
return E.values()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.