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) } } } 
  • ReferenceError: ok no está definido en QUnitAsserter.assertTrue en Kotlin Javascript
  • kotlin verificar campos de input
  • test de unidad LogstashEncoder está configurado correctamente
  • Analizando json con API remota rota
  • ¿Cómo recuperar datos de una database de Firebase con Kotlin?
  • Artículos duplicates en Set
  • No se puede usar fontawesomefx con kotlin y tornadofx
  • ¿Cómo implementar el module de piso para cada tipo de número en Kotlin?
  • Clases de datos de Json a kotlin
  • ¿Se puede sobrepasar var con val con class henetworkingada en Kotlin?
  • Android: Kotlin con cuchillo de mantequilla