Is vararg a pointer in Kotlin?

Mestring af Spread-operatoren (*) i Kotlin

13/09/2017

Rating: 4.63 (2189 votes)

Har du nogensinde set en stjerne (*) foran en variabel i et Kotlin-funktionskald og undret dig over, hvad den gør? Din første tanke var måske: "Wow, har Kotlin pointers?" Svaret er et rungende nej. Den stjerne er Kotlins kraftfulde spread-operator, et syntaktisk værktøj, der markant forbedrer fleksibiliteten i din kode, især når du arbejder med funktioner, der accepterer et variabelt antal argumenter. Denne operator lader dig 'pakke ud' eller 'sprede' elementerne fra et array eller en samling og overføre dem som individuelle argumenter til en funktion. I denne artikel vil vi dykke ned i, hvad spread-operatoren er, hvordan den fungerer sammen med vararg-nøgleordet, og hvordan du kan mestre den til at skrive renere og mere dynamisk kode.

How to use the operator * in Kotlin?
As already answered by zsmb13, the operator * is also available in Kotlin: fun main (args: Array) { val a = arrayOf (1, 2, 3) val b = arrayOf (*a, 4, 5, 6) println (b.contentToString ()) }
Indholdsfortegnelse

Hvad er 'vararg' i Kotlin?

Før vi fuldt ud kan forstå spread-operatoren, må vi først forstå dens tætte partner: vararg-nøgleordet. vararg er en forkortelse for 'variable number of arguments' (variabelt antal argumenter). Når du markerer en funktionsparameter med vararg, fortæller du Kotlin-kompileren, at denne funktion kan acceptere nul eller flere argumenter af den specificerede type for den pågældende parameter.

Lad os se på en simpel funktion:

fun printNavne(vararg navne: String) { println("Modtagne navne:") for (navn in navne) { println("- $navn") } }

Denne funktion, printNavne, kan nu kaldes med et vilkårligt antal strenge:

fun main() { printNavne("Alice", "Bob") // Kaldes med to argumenter println("-----") printNavne("Charlie", "David", "Eve", "Frank") // Kaldes med fire argumenter println("-----") printNavne() // Kaldes uden argumenter }

Internt behandler Kotlin vararg-parameteren som et array af den specificerede type (i dette tilfælde Array<String>). Dette giver os mulighed for at iterere over den, som vi gjorde i eksemplet.

Regler for 'vararg'

Der er et par vigtige regler at huske på:

  • En funktion kan kun have én vararg-parameter.
  • I modsætning til Java behøver vararg-parameteren ikke at være den sidste parameter i funktionssignaturen. Hvis den ikke er den sidste, skal de efterfølgende argumenter dog overføres ved hjælp af navngivne argumenter.

Introduktion til Spread-operatoren (*)

Nu hvor vi forstår vararg, hvad sker der så, hvis vi allerede har vores data i et array? Lad os sige, vi har et array af navne og vil bruge vores printNavne-funktion.

val team = arrayOf("Grace", "Heidi", "Judy") // Dette virker IKKE: // printNavne(team)

Hvis du prøver at køre ovenstående kode, vil du få en kompileringsfejl: Type mismatch. Fejlen opstår, fordi printNavne-funktionen forventer individuelle String-argumenter (String, String, ...), men vi giver den et enkelt objekt: et Array<String>. Funktionen ved ikke, at den skal behandle elementerne inde i arrayet som separate argumenter.

Det er her, spread-operatoren kommer ind i billedet. Ved at placere en stjerne (*) foran arrayet, instruerer vi Kotlin til at 'pakke arrayet ud' og overføre hvert element som et selvstændigt argument.

Den korrekte måde at kalde funktionen på er:

val team = arrayOf("Grace", "Heidi", "Judy") // Dette virker: printNavne(*team)

Dette er den centrale funktion af spread-operatoren. Det er vigtigt at understrege, at dette er ikke en pointer, som man kender det fra sprog som C++. Det er udelukkende en syntaktisk mekanisme til at håndtere argumentlister.

Praktiske Eksempler og Avanceret Brug

Lad os bygge videre på et mere komplekst eksempel for at se spread-operatoren i aktion i forskellige scenarier.

Kombination af Arrays og Enkelte Værdier

En af de mest kraftfulde funktioner ved spread-operatoren er muligheden for at kombinere flere arrays og individuelle værdier i et enkelt funktionskald. Antag, at vi har en funktion til at samle en liste over deltagere til en konference.

fun samlDeltagere(vararg deltagere: String): List<String> { return deltagere.toList() } val udviklere = arrayOf("Ada", "Linus") val designere = arrayOf("Susan", "Jony") val alleDeltagere = samlDeltagere( "Konferencier", // Et individuelt argument *udviklere, // Spreder det første array "Gæstetaler", // Endnu et individuelt argument *designere // Spreder det andet array ) println(alleDeltagere) // Output: [Konferencier, Ada, Linus, Gæstetaler, Susan, Jony]

Bag kulisserne opretter Kotlin effektivt en ny midlertidig array, der samler alle disse værdier i den rigtige rækkefølge, før den kalder funktionen. Dette gør koden utrolig udtryksfuld og let at læse.

What is a spread operator in Kotlin?
The spread operator is used to pass multiple arguments in places where more than one argument is expected. In Kotlin, the spread operator can be used with function parameters prefixed with the vararg keyword. The vararg keyword indicates that a function accepts a variable number of arguments and can be used with both generic and non-generic types.

Denne teknik kan også bruges til at kombinere arrays direkte:

val alleTechFolk = arrayOf(*udviklere, *designere) println(alleTechFolk.joinToString()) // Output: Ada, Linus, Susan, Jony

Håndtering af Lister og Primitive Arrays

Hvad hvis dine data er i en List i stedet for et Array? Spread-operatoren virker kun direkte på arrays. Heldigvis er det let at konvertere:

val managerListe = listOf("Steve", "Bill") // Fejl: spread-operatoren kan ikke anvendes på en List // samlDeltagere(*managerListe) // Korrekt: Konverter først til et array samlDeltagere(*managerListe.toTypedArray())

Et lignende problem opstår med Kotlins specialiserede primitive arrays som IntArray, LongArray osv. Disse er optimeret til ydeevne og er ikke det samme som et Array<Int>. Hvis du har en vararg-funktion, der forventer Int, og du prøver at sprede et IntArray, får du en typefejl.

Løsningen er den samme: brug .toTypedArray() for at konvertere det primitive array til et standardiseret, typet array.

fun beregnSum(vararg tal: Int): Int { return tal.sum() } val scores = intArrayOf(10, 20, 30) // Fejl: Type mismatch // val totalFejl = beregnSum(*scores) // Korrekt: Konverter til Array<Int> val totalKorrekt = beregnSum(*scores.toTypedArray()) println(totalKorrekt) // Output: 60

At huske på toTypedArray() er afgørende for at arbejde problemfrit med spread-operatoren og forskellige samlingstyper.

Sammenligningstabel for Funktionskald

For at opsummere de forskellige måder at kalde en vararg-funktion på, er her en hurtig oversigt:

MetodeEksempelkodeBeskrivelse
Direkte ArgumenterberegnSum(5, 10, 15)Den mest basale måde, hvor argumenter angives individuelt.
Et Enkelt Arrayval tal = arrayOf(5, 10, 15)
beregnSum(*tal)
Bruger spread-operatoren til at pakke et eksisterende array ud.
Kombinationval flereTal = arrayOf(10, 15)
beregnSum(5, *flereTal)
Kombinerer individuelle værdier og spredte arrays i ét kald.
Liste eller Primitivt Arrayval talListe = listOf(5, 10, 15)
beregnSum(*talListe.toTypedArray())
Kræver konvertering til et typet array med .toTypedArray() før spredning.

Ofte Stillede Spørgsmål (FAQ)

Her er svar på nogle almindelige spørgsmål om Kotlins spread-operator.

Er spread-operatoren i Kotlin en pointer?

Nej, absolut ikke. Det er en ren syntaktisk funktion, der bruges af kompileren til at transformere et array til en liste af separate argumenter ved funktionskald. Det har intet at gøre med hukommelsesadresser eller den funktionalitet, som pointers har i sprog som C++.

Kan jeg bruge spread-operatoren på en 'List' eller 'Set'?

Ikke direkte. Spread-operatoren virker kun på arrays. Hvis du har en List, et Set eller en anden samling, skal du først konvertere den til et array ved hjælp af .toTypedArray()-funktionen. Eksempel: minFunktion(*minListe.toTypedArray()).

Hvorfor får jeg en 'Type mismatch' fejl, når jeg sender et array til en 'vararg' funktion uden stjernen?

Fordi funktionen forventer en sekvens af individuelle argumenter (f.eks. String, String, String), men du sender den et enkelt objekt, som tilfældigvis er et Array<String>. Kompileren ser en uoverensstemmelse mellem det forventede (flere strenge) og det faktiske (et array-objekt). Spread-operatoren løser dette ved at instruere kompileren til at pakke arrayet ud for dig.

Hvad er den største fordel ved at bruge 'vararg' og spread-operatoren?

Den største fordel er fleksibilitet. Det giver dig mulighed for at designe API'er, der er nemme at bruge i forskellige situationer. En bruger kan enten overføre argumenter direkte eller samle dem dynamisk i et array og overføre dem. Dette fører til mere ren, læsbar og alsidig kode.

Konklusion

Spread-operatoren i Kotlin, repræsenteret ved et simpelt stjernesymbol (*), er et elegant og kraftfuldt værktøj. Selvom det kan virke forvirrende ved første øjekast, er dets formål klart: at bygge bro mellem samlinger af data (arrays) og funktioner, der kræver individuelle argumenter (vararg-funktioner). Ved at mestre brugen af *, herunder hvordan man kombinerer det med individuelle værdier og hvordan man håndterer forskellige samlingstyper med .toTypedArray(), kan du skrive mere udtryksfuld, fleksibel og robust Kotlin-kode. Det er ikke en pointer, men snarere en nøgle til at låse op for et mere dynamisk og flydende API-design.

Hvis du vil læse andre artikler, der ligner Mestring af Spread-operatoren (*) i Kotlin, kan du besøge kategorien Sundhed.

Go up