Kotlin: how to pass a function as parameter to ano

2019-01-11 08:35发布

问题:

Given function foo :

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

We can do:

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

Now, lets say we have the following function:

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

Is there a way I can pass "buz" as a parameter to "foo" ? Something like:

foo("a message", buz)

回答1:

Use :: to signify a function reference, and then:

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 you can now use functions that are class members ("Bound Callable References"), by prefixing the function reference operator with the instance:

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

foo("hi", thatOtherThing::buz)

foo("hi", this::buz)


回答2:

About the member function as parameter:

  1. Kotlin class doesn't support static member function, so the member function can't be invoked like: Operator::add(5, 4)
  2. Therefore, the member function can't be used as same as the First-class function.
  3. A useful approach is to wrap the function with a lambda. It isn't elegant but at least it is working.

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:

apparently this is not supported yet.

more info:

http://devnet.jetbrains.com/message/5485180#5485180

http://youtrack.jetbrains.com/issue/KT-1183



回答4:

Just use "::" in front of method name as 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--
    }
}


回答5:

Kotlin 1.1

use :: to reference method.

like

    foo(::buz) // calling buz here

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


回答6:

First-class functions are currently not supported in Kotlin. There's been debate about whether this would be a good feature to add. I personally think they should.



标签: kotlin