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) } } } 
  • ¿Cómo proporcionar la class kotlin para las configuraciones de ejecución de eclipse?
  • Singleton con parámetro en Kotlin
  • Cómo alternar la visibilidad de FAB con otro FAB
  • Acceder al valor del parámetro pnetworkingeterminado de una function en Kotlin
  • no se puede llamar al module kotlin desde el module java
  • Importación de objects nesteds / funciones de objects en Kotlin
  • La mejor forma de manejar instancias de objects múltiples
  • Posición de la label `@` en Kotlin cuando se denota el receptor con `this`
  • ¿Hay alguna forma de iterar todos los campos de una class de datos sin usar la reflexión?
  • La propiedad debe inicializarse o ser abstracta
  • Sintaxis de Kotlin para inferir supertipo genérico de subtipo