【问题标题】:Kotlin: how to pass a function as parameter to another?Kotlin:如何将一个函数作为参数传递给另一个函数?
【发布时间】:2013-04-13 19:06:03
【问题描述】:

给定函数 foo:

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

我们可以做到:

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

现在,假设我们有以下函数:

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

有没有办法可以将“buz”作为参数传递给“foo”? 比如:

foo("a message", buz)

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    使用:: 表示函数引用,然后:

    fun foo(msg: String, bar: (input: String) -> Unit) {
        bar(msg)
    }
    
    // my function to pass into the other
    fun buz(input: String) {
        println("another message: $input")
    }
    
    // someone passing buz into foo
    fun something() {
        foo("hi", ::buz)
    }
    

    Since Kotlin 1.1 您现在可以使用作为类成员的函数(“Bound Callable References”),方法是在函数引用运算符前面加上实例:

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

    【讨论】:

    • 如果我错了,请纠正我,但似乎只能以这种方式传递顶级函数(即不属于某个类);类方法不能:-(
    • 可以传递成员引用,但在这种情况下,这将是一个 2 参数函数,第一个参数需要类的实例。更好的方法是用关闭类的 lambda 包装成员函数。假设以上所有内容都在一个类中:fun something() { foo("hi", { buz(it) }) }
    • 如果您在同一个类中操作,似乎可以传入属于某个类的函数,从 kotlin 1.1 开始,您可以使用 this::function
    • 另外,如果你想让函数参数可以为空,只需将类型声明用括号括起来,最后加上一个问号。例如bar: ((m: String) -> Unit)?
    • @MartyMiller 他们不是。参数m为foo,另一个参数是变量bar中传递给函数的函数类型的参数名。
    【解决方案2】:

    关于成员函数作为参数:

    1. Kotlin 类不支持静态成员函数,因此不能像这样调用成员函数: 运算符::add(5, 4)
    2. 因此,成员函数不能与 First-class 函数一样使用。
    3. 一种有用的方法是用 lambda 封装函数。它并不优雅,但至少它是有效的。

    代码:

    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) })
    }
    

    【讨论】:

    • 在当前的 Kotlin 中,您现在可以使用成员函数作为引用。您现在应该更新此答案。
    • 通过在伴生对象中定义函数,调用代码变得更好,并且每次都不会创建新的 Operator 实例。这看起来像是 Java 中的静态乐趣
    • 很好的解决方案,这是我发现当函数在类中时唯一有效的方法。我不认为它丑陋但美丽,几乎看起来像一个角度模板变量但用于代码。
    【解决方案3】:

    只需在方法名前使用“::”

    fun foo(function: () -> (Unit)) {
       function()
    }
    
    fun bar() {
        println("Hello World")
    }
    

    foo(::bar) 输出 : Hello World

    【讨论】:

    • 此代码无法编译。 “function()”需要一个参数
    【解决方案4】:

    科特林 1.1

    使用:: 引用方法。

    喜欢

        foo(::buz) // calling buz here
    
        fun buz() {
            println("i am called")
        }
    

    【讨论】:

      【解决方案5】:

      如果你想传递 settergetter 方法。

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

      用法:

      private var width: Int = 1
      
      setData({ width = it }, { width })
      

      【讨论】:

        【解决方案6】:

        Jason Minard 的回答很好。这也可以使用lambda 来实现。

        fun foo(m: String, bar: (m: String) -> Unit) {
            bar(m)
        }
        
        val buz = { m: String ->
            println("another message: $m")
        }
        

        可以用foo("a message", buz)调用。

        您还可以使用typealias 使这更干一点。

        typealias qux = (m: String) -> Unit
        
        fun foo(m: String, bar: qux) {
            bar(m)
        }
        
        val buz: qux = { m ->
            println("another message: $m")
        }
        

        【讨论】:

          【解决方案7】:

          这是一个简单的例子,我将乘法函数作为参数传递给另一个函数。

          fun main(){
              result(10,3,::multiplication)// pass function as parameter wow kotlin amazing
          }
          fun multiplication(first:Int,second:Int):Int{
              return first*second
          }
          fun result(firstOne:Int,secondOne: Int,fn:(Int,Int)->Int){
              val result=fn(firstOne,secondOne)
              print(result)
          
          }
          

          【讨论】:

            【解决方案8】:

            【讨论】:

            • 这已被添加到 Kotlin,因此这个答案现在不正确。
            【解决方案9】:

            如果这是您使用该函数的唯一地方,您也可以使用 lambda 内联执行此操作

            fun foo(m: String, bar: (m: String) -> Unit) {
                bar(m)
            }
            
            foo("a message") {
                m: String -> println("another message: $m")
            }
            //Outputs: another message: a message
            

            【讨论】:

              【解决方案10】:

              另一个例子:

               fun foo(x:Int, Multiply: (Int) -> (Int)) {
                  println(Multiply(x))
               }
               fun bar(x:Int):Int{
                  return  x * x
               }
               foo(10, ::bar)
              

              【讨论】:

                【解决方案11】:

                Kotlin 目前不支持一流的函数。关于这是否是一个很好的添加功能一直存在争议。我个人认为他们应该这样做。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-08-19
                  • 1970-01-01
                  • 2023-01-12
                  • 2013-11-19
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多