以两个方法为参数的调用方法

时间:2018-10-30 08:25:39

标签: kotlin

当我有一个将另一个函数作为参数的函数时,我可以这样称呼它:

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

foo("a message") { 
    println("message: $it")
}

有没有一种方法可以像上面那样用一个方括号来调用它?我只知道这种方式:

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

foo("a message", { println("message 1: $it") }, { println("message 2: $it") } )

3 个答案:

答案 0 :(得分:1)

只是为了好玩...这里有一些尝试来获得与您所要求的相似的东西。请注意,除了“标准”方法,我不能真正推荐其他方法;-)(即免责声明)

  1. 原样为

    fun method1(s: String,
                m1: (String) -> String,
                m2: (String) -> String) {
        println(m1(s))
        println(m2(s))
    }
    method1("test", { "m1: $it" }) {
        "m2: $it"
    }
    // if you like with or without mentioning the parameter names:
    method1("test",
        m1 = { "m1: $it" },
        m2 = { "m2: $it" }
    )
    
    // 1b. using own methods and supplying method references
    fun m1(s : String) = "m1: $s"
    fun m2(s : String) = "m2: $s"
    method1("test1b", ::m1 /*, ::m2 */) {
        "m2: $it"
    }
    
  2. 使用invoke ...

    class Method2(val s: String,
                  val m1: (String) -> String) {
        operator fun invoke(m2: (String) -> String) {
            println(m1(s))
            println(m2(s))
        }
    }
    
    fun method2(s: String,
                m1: (String) -> String) = Method2(s, m1)
    method2("test2") {
        "m1: $it"
    }() {
        "m2: $it"
    }
    
  3. 使用具有自身丑陋扩展功能的配对供应商

    fun method3(s: String,
                m1AndM2: () -> Pair<(String) -> String, (String) -> String>) {
        m1AndM2().let { (m1, m2) ->
            println(m1(s))
            println(m2(s))
        }
    }
    
    infix fun <T : (String) -> String> T.and(m2: (String) -> String) = Pair(this, m2)
    method3("test3") {
        { s: String -> "m1: $s" } and // note: the "s: String" is mandatory as the compiler can not infer the type
            { "m2: $it" }
    }
    
    // 3b. using a div operator as delimiter (still a hack):
    operator fun <T : (String) -> String> T.div(m2: (String) -> String) = Pair(this, m2)
    method3("test3b") {
        { s: String -> "m1: $s" } / {
            "m2: $it"
        }
    }
    

注意:您甚至可以使用一种解决方案,甚至可以提出更好的解决方案。我仍然会坚持第一个变体...也许方法参考在您的情况下会更有帮助。我什至发现带有命名参数的变体更好,然后尝试完成诸如块链之类的事情。而且请不要忘记:其他人(可能更重要的是您将来的自己)应该仍然可以阅读代码;-)

答案 1 :(得分:0)

您可以使用方法引用。下面的示例使用“静态”函数,很酷的事情是您也可以引用“实例函数”(闭包):

object Xxx {
    @JvmStatic
    fun main(args: Array<String>) {
        service("initial", ::toUpperCase, ::withSuffix)
    }

    fun toUpperCase(s: String) = s.toUpperCase()
    fun withSuffix(s: String) = "$s.mySuffix"

    fun service(argument: String, vararg enhancers: (String) -> String) {
        println(enhancers.fold(argument) { s, e -> e(s) })
    }
}

答案 2 :(得分:0)

我试图返回一个以另一个函数为参数的函数,以查看是否可以在()之外获得两个lambda。

fun foo(m:String,bar1:(m:String)->Unit) : (bar2:(m:String)->Unit)->Unit
{
    bar1(m)
    return { bar2: (m: String) -> Unit -> bar2(m) }
}

结果证明我不能。我最后在第一个函数前后加上了一对(),以便编译器知道最后一个lambda是返回函数的参数,而不是假定尝试在括号内的参数列表之外传递两个lambda表达式。 / p>

(foo("a message"){println("message 1: $it")}){println("message 2: $it")}

foo("a message"){println("message 1: $it")}(){println("message 2: $it")}

显然,这些看起来没有任何改善。我认为

foo("a message", { println("message 1: $it") }, { println("message 2: $it") } )

foo("a message", { println("message 1: $it") }){ println("message 2: $it")}

足够好。

有趣的是,这在Swift中是允许的

func foo (m:String,bar1 : ((String) -> Void) ) -> (_:((String) -> Void))->Void
{
    bar1(m)
    return {bar2 in bar2(m)}
}
foo(m: "test"){print("m1: \($0)")}{print("m2: \($0)")}