Kotlin: método genérico y para bucle preguntando por iterador ()

Este es un método genérico simple, y al pasar los valores, el args in for loop causa un error que dice:

El range for-loop debe tener el método iterator ()

fun main(args: Array<String>) { val arr: IntArray = intArrayOf(1,2,3,4) val charA: CharArray = charArrayOf('a','b','c','d') printMe(arr) printMe(charA) } fun <T>printMe(args: T){ for (items in args){ println(items) } } 

¿Cómo lo hago iterar a través de los valores de ambos char[] y array

for-loop en Kotlin funciona por convención, buscando estáticamente un miembro del operador llamado iterator que debe devolver algo que pueda ser iterado, es decir, algo que tiene a su vez miembros del operador a next y hasNext .

se requiere un modificador de operator en dichos miembros para especificar que el miembro debe satisfacer alguna convención, concretamente la convención de iteración.

Como args es de tipo T y no hay un miembro iterator en cada posible tipo T , no se puede iterar fácilmente.

Sin embargo, puede proporcionar un parámetro adicional a printMe , que sabe cómo get un iterador de una instancia de T , y luego usarlo para get un iterador y repetirlo:

 fun main(args: Array<String>) { val arr: IntArray = intArrayOf(1,2,3,4) val charA: CharArray = charArrayOf('a','b','c','d') printMe(arr, IntArray::iterator) printMe(charA, CharArray::iterator) } fun <T> printMe(args: T, iterator: T.() -> Iterator<*>) { for (item in args.iterator()) { println(item) } } 

Aquí T.() -> Iterator<*> es un tipo que denota una function con receptor . Las instancias de ese tipo se pueden invocar en T como si fueran sus extensiones.

Este fragment funciona porque el iterador devuelto tiene una function de extensión de operador Iterator<T>.iterator() = this que simplemente devuelve ese iterador, lo que permite recorrer el iterador con un for-loop.

Esto es en realidad un poco sutil.

El problema key es que la variable arr es del tipo IntArray y IntArray no se deriva de la Array . De manera similar, mientras IntArray tiene una function de iterator() , no implementa Iterable<> .

Lo mismo ocurre para la variable CharArray .

De hecho, IntArray CharArray y Array<T> no parecen tener una class base o interfaz común distinta de Any . Entonces, estás atrapado pasando un object y haciendo una comprobación de tipo en printMe , o usando sobrecarga.

Una versión de verificación de tipo se vería como

 printMe(args:Any) { if(args is IntArray) { for(item in args) { println(item) } } else if (args is CharArray) { for(item in args) { println(item) } } else { println("Not an IntArray or a CharArray") } } 

La sobrecarga se vería así

 printMe(args:IntArray) { for(item in args) { println(item) } } printMe(args:CharArray) { for(item in args) { println(item) } } 

La sobrecarga de IMO es la mejor opción ya que no puede terminar pasando un object que no puede manejar por error.

El problema es que el comstackdor no sabe que está pasando una Array y T puede ser de cualquier tipo.

Una forma de solucionar esto sería usando is operator:

 fun <T>printMe(args: T){ if(args is Array<*>) { for (items in args) { println(items) } } } 
  • ¿Asignación de collections anidadas con hibernación de annotations JPA? Mapa <Clave, Establecer <Valores >>
  • El selector común Kotlin anko no funciona como en los ejemplos proporcionados
  • ¿Es posible implementar desestructuración personalizada para classs no de datos en Kotlin?
  • Extensiones Kotlin references no resueltas
  • kotlin inversa boolean seguro de casting
  • Enumera y con en Kotlin
  • Arreglo 2D en Kotlin
  • ¿De qué se trata este package "KotlinRulezzz"?
  • Henetworkingar class con constructor primario
  • ¿Cómo definir properties propias para models basados ​​en Jena?
  • ¿Cómo get la class Java del param del método genérico?