Kotlin: Comment travailler avec la Liste des conversions: Décoché Cast: kotlin.les collections.Liste<Kotlin.Tout?> de kotlin.colletions.Liste<Waypoint>
Je veux écrire une fonction qui retourne chaque élément dans un List
qui n'est pas le premier ou le dernier élément (d'un point). La fonction reçoit un générique List<*>
comme entrée. Un résultat ne peut être renvoyé que si les éléments de la liste sont du type Waypoint
:
fun getViaPoints(list: List<*>): List<Waypoint>? {
list.forEach { if(it !is Waypoint ) return null }
val waypointList = list as? List<Waypoint> ?: return null
return waypointList.filter{ waypointList.indexOf(it) != 0 && waypointList.indexOf(it) != waypointList.lastIndex}
}
Lors de la coulée de la List<*>
à List<Waypoint>
, je reçois l'avertissement:
Décoché Cast: kotlin.les collections.Liste
de kotlin.colletions.Liste
Je ne peux pas trouver un moyen de la mettre en œuvre autrement. Quelle est la bonne façon de mettre en œuvre cette fonction sans cet avertissement?
InformationsquelleAutor lukle | 2016-04-12
Vous devez vous connecter pour publier un commentaire.
Dans Kotlin, il n'y a aucun moyen de vérifier les paramètres génériques lors de l'exécution dans le cas général (comme juste vérifier les éléments d'un
List<T>
, qui n'est qu'un cas particulier), de sorte que le moulage d'un générique à un autre, avec différents paramètres génériques de soulever un avertissement, sauf si la distribution se trouve dans la variance de limites.Il existe différentes solutions, cependant:
Vous avez vérifié que le type et vous êtes tout à fait sûr que le casting est sûr. Étant donné que, vous pouvez supprimer l'avertissement avec
@Suppress("UNCHECKED_CAST")
.Utilisation
.filterIsInstance<T>()
fonction qui vérifie les types d'élément et renvoie une liste avec les éléments du passé de type:ou même en une seule instruction:
Cela va créer une nouvelle liste du type désiré (évitant ainsi décoché coulé à l'intérieur), en introduisant un peu de surcharge, mais dans le même temps, il vous permet d'économiser de l'itération à travers le
list
et vérifier les types (enlist.foreach { ... }
ligne), afin de ne pas être perceptible.Écrire une fonction utilitaire qui vérifie le type et retourne la même liste si le type est correct, donc de l'encapsulation de la distribution (toujours désactivée à partir du compilateur de point de vue) à l'intérieur:
Avec l'utilisation:
filterIsInstance
et de la première liste contient les éléments d'un type différent de votre code silencieusement filtrer les. Parfois, c'est ce que vous voulez, mais parfois, vous pourriez plutôt avoir uneIllegalStateException
ou similaire levée. Si le plus tard est le cas, alors vous pouvez créer votre propre méthode pour vérifier et puis cast:inline fun <reified R> Iterable<*>.mapAsInstance() = map { it.apply { check(this is R) } as R }
.apply
ne renvoie pas la valeur de retour de la lambda, il renvoie la réception de l'objet. Vous voudrez probablement utiliser.takeIf
si vous voulez l'option de retourner une valeur null.Dans le cas de classes génériques jette ne peut pas être vérifié, car le type de l'information est effacée dans l'exécution. Mais vous de vérifier que tous les objets de la liste sont
Waypoint
s de sorte que vous pouvez simplement supprimer le message d'avertissement avec@Suppress("UNCHECKED_CAST")
.Pour éviter de telles mises en garde vous devez passer un
List
des objets convertiblesWaypoint
. Lorsque vous utilisez*
mais en essayant d'accéder à cette liste, comme une liste tapée vous aurez toujours besoin d'avoir un casting et cette distribution sera désactivée.Pour améliorer @raccourci réponse voici ma solution:
Cela vous donne la
List<Waypoint>
si tous les éléments peuvent être coulé, null sinon.J'ai fait un peu de variation à @raccourci réponse lorsqu'il est utilisé pour vérifier Serializable pour les objets de la Liste :
Cannot access 'Serializable': it is internal in 'kotlin.io'
Au lieu de
J'aime faire
Pas sûr de la façon performante, mais pas de mise en garde au moins.