Recientemente me encontré con un problema en el que tenía una función que tenía que devolver una matriz de I s, en forma de todos los valores de la enumeración E , con E implementando la interfaz I , con cada código que me vino a la mente, el compilador se quejó de la falta de coincidencia de tipos:
Error:(x, x) Kotlin: Type mismatch: inferred type is Array<E> but Array<I> was expectedUn ejemplo mínimo:
interface I {} enum class E: I { A, B, C; } fun getMoreInterfaces(): Array<I> { return E.values() } Esto sucede cuando se intenta asignar E.values() a una variable de tipo Array<I> . Estoy seguro de que esto debería ser posible ya que E implementa I
Otra cosa que se me ocurrió durante la prueba es que funciona bien cuando se usa así:
interface I {} enum class E: I { A, B, C; } fun getMoreInterfaces(): Array<I> { return arrayOf(EA, EB, EC) }Investigué mucho sobre este tema pero no tuve suerte (¿tal vez elegí la forma incorrecta de describirlo?)
En Kotlin, a diferencia de Java, Array<T> es invariable en T , por lo tanto, para E que es un subtipo de I , Array<E> y Array<I> no son subtipos entre sí. Ver: Variación .
Dado que los tipos Array<T> también almacenan el tipo de elemento y no pueden estar sujetos a conversiones completamente descontroladas , la mejor manera de resolver esto es crear una matriz separada.
Puede hacerlo creando una matriz manualmente y rellenándola con los elementos, como en su ejemplo (o usando el constructor Array(n) { ... } ), o use .toTypedArray() aplicado a la representación de lista de la matriz ( .asList() ):
fun getMoreInterfaces(): Array<I> { return E.values().asList().toTypedArray() } Pero, básicamente, puede usar List<I> si no está en un código crítico para el rendimiento, que es más idiomático para Kotlin que trabajar con arreglos, y también más simple.
Ver también: Diferencia entre los tipos de lista y matriz en Kotlin
Array es un tipo genérico invariable en Kotlin, por lo que si necesita devolver una instancia de Array<I> , no puede devolver Array<E> en su lugar, incluso si E es un subtipo de I .
Pero en caso de que solo consuma valores de la matriz devuelta, puede declarar su tipo como Array<out I> . Este tipo es una proyección covariante del tipo Array<I> y le permite devolver tanto Array<I> como Array<E> .
interface I {} enum class E: I { A, B, C } fun getMoreInterfaces(): Array<out I> { return E.values() }