Operador de asterisco de Kotlin antes del nombre de la variable o del operador de propagación en Kotlin


97

Quiero saber qué hace exactamente el asterisco antes del nombre de la variable en Kotlin. Vi esto ( *args) en el ejemplo de Spring boot Kotlin :

@SpringBootApplication
open class Application {

    @Bean
    open fun init(repository: CustomerRepository) = CommandLineRunner {
        repository.save(Customer("Jack", "Bauer"))
        repository.save(Customer("Chloe", "O'Brian"))
        repository.save(Customer("Kim", "Bauer"))
        repository.save(Customer("David", "Palmer"))
        repository.save(Customer("Michelle", "Dessler"))
    }
}

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}

Respuestas:


164

El *operador se conoce como el operador de propagación en Kotlin.

De la referencia de Kotlin ...

Cuando llamamos a una función vararg, podemos pasar argumentos uno por uno, por ejemplo, asList (1, 2, 3), o, si ya tenemos una matriz y queremos pasar su contenido a la función, usamos la extensión operador (prefijo la matriz con *):

Se puede aplicar a una matriz antes de pasarla a una función que acepte varargs.

Por ejemplo...

Si tiene una función que acepta un número variado de argumentos ...

fun sumOfNumbers(vararg numbers: Int): Int {
    return numbers.sum()
}

Puedes pasarle una matriz así ...

val numbers = intArrayOf(2, 3, 4)
val sum = sumOfNumbers(*numbers)
println(sum) // Prints '9'

Notas:

  • El *operador también es el operador de multiplicación (por supuesto).
  • El operador solo se puede usar al pasar argumentos a una función. El resultado de la operación no se puede almacenar porque no arroja ningún valor (es azúcar puramente sintáctico).
  • El operador puede confundir a algunos programadores de C / C ++ al principio porque parece que se está quitando la referencia a un puntero. No lo es; Kotlin no tiene noción de punteros .
  • El operador se puede utilizar entre otros argumentos cuando se llama a una función vararg. Esto se demuestra en el ejemplo aquí .
  • El operador es similar a la applyfunción en varios lenguajes de programación funcional.

¿El operador de propagación es una matriz en línea? Por ejemplo, para la matriz a = [1, 2, 3] funWithVararg (* a) inserta en funWithVararg (1,2,3)? Me refiero a nivel de código de bytes.
David

22

Además de las respuestas que fueron directamente hacia "¿¡qué es esto!?!", A menudo tiene el caso en el que tiene un Listy desea pasarlo a una función que espera un vararg. Para esto, la conversión es:

someFunc(x, y, *myList.toTypedArray())

Suponiendo que el último parámetro de someFunces varargdel mismo tipo que los elementos de la lista.


Muchas gracias! Esto debería estar en los documentos oficiales en la sección de operador de propagación como algo a tener en cuenta cuando su operador de propagación no está funcionando.
pleasedesktop

¡Gracias! Realmente útil. ¿Se pregunta qué es "Spread Operator" detrás de escena? ¿Es solo una forma de obtener un valor de varargs?
Nicolas Jafelle

11

Como se describe en la documentación, este es un operador de propagación:

Cuando llamamos a una función vararg, podemos pasar argumentos uno por uno, por ejemplo, asList (1, 2, 3), o, si ya tenemos una matriz y queremos pasar su contenido a la función, usamos la extensión operador (prefijo la matriz con *):

val a = arrayOf(1, 2, 3) 
val list = asList(-1, 0, *a, 4)

6

Si una función que acepta un parámetro vararg (número variable de argumentos) como:

fun sum(vararg data:Int)
{
   // function body here         
}

Ahora para llamar a este método, podemos hacer:

sum(1,2,3,4,5)

Pero, ¿qué pasa si tenemos estos valores en una matriz, como:

val array= intArrayOf(1,2,3,4,5)

luego, para llamar a este método tenemos que usar el operador de propagación, como:

 sum(*array)

Aquí, * (operador de propagación) pasará todo el contenido de esa matriz.

* matriz es equivalente a 1,2,3,4,5

Pero espere un minuto, ¿qué pasa si lo llamamos así? sum(array) Nos dará un error de tiempo de compilación de Type Mismatch:

Type mismatch.
Required:Int
Found:IntArray

El problema es que la sumfunción acepta un vararg Intparámetro (que acepta un valor como: 1,2,3,4,5) y si pasamos una matriz, se pasará como IntArray.


5

En Java, puede pasar una matriz como está, pero una ventaja de desempaquetar una matriz con el operador de extensión *es que el operador de extensión le permite combinar los valores de una matriz y algunos valores fijos en una sola llamada. Java no admite esto.


1
Voto a favor, porque me pregunté por qué lo implementaron así. Todavía no estoy 100% seguro de ello. Quiero decir, ¿no podrían simplemente inferir esto en la mayoría de los casos?
Tim Büthe

1
@ TimBüthe En algunos casos, no sería posible inferirlo, considere los siguientes casos val resultOne = arrayOf(intArrayOne, intArrayTwo)y val resultTwo = arrayOf(*intArrayOne, *intArrayTwo). Tipo de resultOney resultTwoson respectivamente Array<Int>y Array<Array<Int>>. Creo que esa es una de las razones
Farid
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.