it-swarm.com.de

Kotlin: Wie kann man eine Funktion als Parameter an einen anderen übergeben?

Gegebene Funktion foo:

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

Wir können tun:

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

Nehmen wir an, wir haben folgende Funktion:

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

Gibt es eine Möglichkeit, "buz" als Parameter an "foo" zu übergeben? Etwas wie:

foo("a message", buz)
71
mhshams

Verwenden Sie ::, um eine Funktionsreferenz zu kennzeichnen, 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)
}

Seit Kotlin 1.1 können Sie jetzt Funktionen verwenden, die Klassenmitglieder sind ("Bound Callable References").

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

foo("hi", thatOtherThing::buz)

foo("hi", this::buz)
110
Jayson Minard

Über die Elementfunktion als Parameter:

  1. Die Kotlin-Klasse unterstützt keine statische Memberfunktion. Daher kann die Memberfunktion nicht wie folgt aufgerufen werden: Operator :: add (5, 4) 
  2. Daher kann die Member-Funktion nicht wie die First-Class-Funktion verwendet werden.
  3. Ein nützlicher Ansatz besteht darin, die Funktion mit einem Lambda zu umschließen. 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) })
}
5
Rui Zhou
3
mhshams

Verwenden Sie einfach "::" vor dem 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--
    }
}
1
erluxman

Jason Minards Antwort ist gut. Dies könnte auch mit einem lambdaerreicht werden.

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

val buz = { m: String ->
    println("another message: $m")
}

Welches kann mit foo("a message", buz) aufgerufen werden.

Sie können dies auch mit einem typealiasein wenig mehr DRY machen.

typealias qux = (m: String) -> Unit

fun foo(m: String, bar: qux) {
    bar(m)
}

val buz: qux = { m ->
    println("another message: $m")
}
0
flesk

Wenn Sie setter und getter Methoden übergeben möchten.

private fun setData(setValue: (Int) -> Unit, getValue: () -> (Int)) {
    val oldValue = getValue()
    val newValue = oldValue * 2
    setValue(newValue)
}

Verwendungszweck:

private var width: Int = 1

setData({ width = it }, { width })
0
CoolMind

Kotlin 1.1 

verwenden Sie ::, um die Methode zu referenzieren.

mögen

    foo(::buz) // calling buz here

    fun buz() {
        println("i am called")
    }