Kotlin: Cómo trabajar con los cambios de Lista: Lanzamiento no seleccionado: kotlin.collections.List <Kotlin.Any?> A kotlin.colletions.List <Waypoint>

Quiero escribir una function que devuelva todos los elementos en una List que no sea el primero o el último elemento (un punto de vía). La function obtiene una List<*> genérica List<*> como input. Un resultado solo debe devolverse si los elementos de la list son del tipo 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} } 

Al enviar la List<*> a la List<Waypoint> , aparece la advertencia:

Cast no seleccionado: kotlin.collections.List a kotlin.colletions.List

No puedo encontrar una manera de implementarlo de otra manera. ¿Cuál es la forma correcta de implementar esta function sin esta advertencia?

Solutions Collecting From Web of "Kotlin: Cómo trabajar con los cambios de Lista: Lanzamiento no seleccionado: kotlin.collections.List <Kotlin.Any?> A kotlin.colletions.List <Waypoint>"

En Kotlin, no hay forma de verificar los parameters generics en time de ejecución en un caso general (como simplemente verificar los elementos de una List<T> , que es solo un caso especial), por lo que plantear un tipo genérico a otro con diferentes parameters generics una advertencia a less que el yeso se encuentre dentro de los límites de varianza .

Sin embargo, hay diferentes soluciones:

  • Has verificado el tipo y estás bastante seguro de que el lanzamiento es seguro. Dado eso, puede suprimir la advertencia con @Suppress("UNCHECKED_CAST") .

     @Suppress("UNCHECKED_CAST") val waypointList = list as? List<Waypoint> ?: return null 
  • Utilice la function .filterIsInstance<T>() , que verifica los types de elementos y devuelve una list con los elementos del tipo pasado:

     val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>() if (waypointList.size != list.size) return null 

    o lo mismo en una statement:

     val waypointList = list.filterIsInstance<Waypoint>() .apply { if (size != list.size) return null } 

    Esto creará una nueva list del tipo deseado (evitando de este modo el uso de list.foreach { ... } en el interior), introduciendo un poco de sobrecarga, pero al mismo time le ahorrará iterar en la list y verificar los types (en list.foreach { ... } línea), por lo que no será notable.

  • Escriba una function de utilidad que compruebe el tipo y devuelva la misma list si el tipo es correcto, encapsulando así el model (aún sin verificar desde el punto de vista del comstackdor) dentro de él:

     @Suppress("UNCHECKED_CAST") inline fun <reified T : Any> List<*>.checkItemsAre() = if (all { it is T }) this as List<T> else null 

    Con el uso:

     val waypointList = list.checkItemsAre<Waypoint>() ?: return null 

En el caso de las classs genéricas, las conversiones no se pueden verificar porque la información del tipo se borra en el time de ejecución. Pero comtesting que todos los objects de la list sean Waypoint s, por lo que puede suprimir la advertencia con @Suppress("UNCHECKED_CAST") .

Para evitar tales advertencias, debe pasar una List de objects convertibles a Waypoint . Cuando estás usando * pero tratando de acceder a esta list como una list de types, siempre necesitarás un yeso y este lanzamiento no se marcará.