3 votes

Kotlin : Retourner Array<E> d'une fonction avec type de retour Array<I> si E est une classe enum qui implémente l'interface I

Récemment, j'ai rencontré un problème avec une fonction qui devait renvoyer un tableau de I sous la forme de toutes les valeurs de l'enum E , avec E la mise en œuvre de l'interface I Avec chaque code qui m'est venu à l'esprit, le compilateur s'est plaint d'une incompatibilité de type :

Error:(x, x) Kotlin: Type mismatch: inferred type is Array<E> but Array<I> was expected

Un exemple minimal :

    interface I {}
    enum class E: I {
        A, B, C;
    }
    fun getMoreInterfaces(): Array<I> {
        return E.values()
    }

Cela se produit lorsque l'on essaie d'assigner E.values() à une variable de type Array<I> Je suis certain que cela devrait être possible puisque E met en œuvre I .

Une autre chose que j'ai constatée lors de mes tests est que le système fonctionne parfaitement lorsqu'il est utilisé de cette manière :

    interface I {}
    enum class E: I {
        A, B, C;
    }
    fun getMoreInterfaces(): Array<I> {
        return arrayOf(E.A, E.B, E.C)
    }

J'ai fait beaucoup de recherches sur ce sujet, mais sans succès (peut-être ai-je choisi la mauvaise manière de le décrire ?)

5voto

hotkey Points 119

En Kotlin, contrairement à Java, Array<T> est invariant sur T Ainsi, pour E qui est un sous-type de I , Array<E> y Array<I> ne sont pas des sous-types les uns des autres. Voir : Variance .

Étant donné que le Array<T> stockent également le type d'article et ne peuvent pas être soumis à des contrôles complets. les plâtres non contrôlés Le meilleur moyen de résoudre ce problème est de créer un tableau séparé.

Vous pouvez le faire en créant manuellement un tableau et en le remplissant avec les éléments, comme dans votre exemple (ou en utilisant le constructeur Array(n) { ... } ), ou utiliser .toTypedArray() appliquée à la représentation en liste du tableau ( .asList() ):

fun getMoreInterfaces(): Array<I> {
    return E.values().asList().toTypedArray()
}

(échantillon exécutable)

Mais fondamentalement, vous pouvez simplement utiliser un List<I> si vous n'êtes pas dans un code critique en termes de performance, ce qui est plus idiomatique pour Kotlin que de travailler avec des tableaux, et aussi plus simple.

Voir aussi Différence entre les types List et Array en Kotlin

1voto

Ilya Points 8216

Array est un type générique invariant en Kotlin, donc si vous avez besoin de retourner une instance de Array<I> vous ne pouvez pas revenir Array<E> au lieu de cela, même si E est un sous-type de I .

Mais si vous n'êtes que consommation du tableau retourné, vous pouvez déclarer son type comme étant Array<out I> . Ce type est une projection covariante du type Array<I> et il vous permet de renvoyer à la fois Array<I> y Array<E> .

interface I {}
enum class E: I {
    A, B, C
}
fun getMoreInterfaces(): Array<out I> {
    return E.values()
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X