2013-04-20 11 views
43

Gegeben Funktion foo:Kotlin: Wie übergibt man eine Funktion als Parameter an einen anderen?

fun foo(m: String, bar: (m: String) -> Unit) { 
    bar(m) 
} 

Wir tun können:

foo("a message", { println("this is a message: $it") }) 
//or 
foo("a message") { println("this is a message: $it") } 

wir nun an, wir die folgende Funktion haben:

fun buz(m: String) { 
    println("another message: $m") 
} 

Gibt es eine Möglichkeit, ich Buz passieren kann“ "Als Parameter für" foo "? Etwas wie:

foo("a message", buz) 

Antwort

52

Verwenden :: eine Funktionsreferenz, um anzuzeigen, und dann:

fun foo(m: String, bar: (m: String) -> Unit) { 
    bar(m) 
} 

// my function to pass into the other 
fun buz(m: String) { 
    println("another message: $m") 
} 

// someone passing buz into foo 
fun something() { 
    foo("hi", ::buz) 
} 

Since Kotlin 1.1 Sie jetzt Funktionen verwenden können, die Klassenmitglieder sind ("Gebundene anrufbare Referenzen „), die von der Funktion Referenzoperator mit der Instanz Vorfixierung:

foo("hi", OtherClass()::buz) 

foo("hi", thatOtherThing::buz) 

foo("hi", this::buz) 
+1

Bitte korrigieren Sie mich, wenn ich falsch liege, aber es scheint, dass nur Top-Level-Funktionen (d. H.gehören nicht zu einer Klasse) kann auf diese Weise weitergegeben werden; Klassenmethoden können nicht :-( –

+5

Ein Memberreferenz kann übergeben werden, aber das wäre in diesem Fall eine 2-Parameter-Funktion, wobei der erste Parameter eine Instanz der Klasse benötigt. Ein besserer Weg ist, die Memberfunktion mit einem Lambda zu umbrechen Angenommen, alle oben genannten wären in einer Klasse: 'Spaß etwas() {foo (" hi ", {buz (it)})}' –

+0

gibt es sowieso, dies zu tun, wenn buz generisch ist und Typ Rückschluss scheitert? –

-3

First-Class-Funktionen sind derzeit nicht in Kotlin unterstützt. Es gab Diskussionen darüber, ob dies ein gutes Feature wäre. Ich persönlich denke, sie sollten es tun.

+1

zuerst Klassenfunktionen werden bereits in Kotlin unterstützt – mhshams

+0

Das ist veraltet, nicht korrekt. –

4

Über die Elementfunktion als Parameter:

  1. Kotlin Klasse nicht statische Elementfunktion, so dass die Elementfunktion unterstützt kann‘ t aufgerufen werden wie: Operator :: hinzufügen (5, 4)
  2. Daher kann die Member-Funktion nicht so wie die First-Class-Funktion verwendet werden.
  3. Ein nützlicher Ansatz besteht darin, die Funktion mit einem Lambda zu umhüllen. Es ist nicht elegant, aber zumindest funktioniert es.

Code:

class Operator { 
    fun add(a: Int, b: Int) = a + b 
    fun inc(a: Int) = a + 1 
} 

fun calc(a: Int, b: Int, opr: (Int, Int) -> Int) = opr(a, b) 
fun calc(a: Int, opr: (Int) -> Int) = opr(a) 

fun main(args: Array<String>) { 
    calc(1, 2, { a, b -> Operator().add(a, b) }) 
    calc(1, { Operator().inc(it) }) 
} 
+3

Im aktuellen Kotlin, Sie jetzt * kann * eine Mitgliedsfunktion als Referenz verwenden Sie sollten diese Antwort jetzt aktualisieren –

+0

Durch die Definition von Funktionen im Companion-Objekt wird der Aufrufcode etwas besser und keine neue Instanz of Operator werden jedes Mal erstellt. Dies würde in Java wie ein statischer Spaß aussehen –

0

Verwenden Sie einfach "::" vor Methodennamen als Parameter

fun main(args: Array<String>) { 
    runAFunc(::runLines) 
} 


fun runAFunc(predicate: (Int) -> (Unit)) { 
    val a = "five" 
    if (a == "five") predicate.invoke(5) else predicate.invoke(3) 

} 

fun runLines(numbers: Int) { 
    var i = numbers 
    while (i > 0) { 
     println("printed number is $i") 
     i-- 
    } 
} 
0

Kotlin 1.1

dieses :: Buz (wenn in gleiche Klasse) oder Klasse() :: buz, falls unterschiedlich

Verwandte Themen