如何在.kt类中使用函数接口

时间:2019-04-01 15:10:15

标签: lambda kotlin functional-interface

我想在java.util.function包中使用某些功能接口,例如DoubleBinaryOperator接口。

我可以在Java中使用它,如下所示:

public enum Operation {
    PLUS("+", Double::sum),
    MINUS("-", (x, y) -> x - y),
    TIMES("*", (x, y) -> x * y),
    DIVIDE("/", (x, y) -> x / y);

    private final String symbol;
    private final DoubleBinaryOperator op;

    Operation(String symbol, DoubleBinaryOperator op) {
        this.symbol = symbol;
        this.op = op;
    }

}

但是在Kotlin中,这对我不起作用,因为Kotlin无法推断参数的类型。

enum class Operation private constructor(private val symbol: String, private val op: DoubleBinaryOperator) {
    PLUS("+", { x, y -> x + y }),
    MINUS("-", { x, y -> x - y }),
    TIMES("*", { x, y -> x * y }),
    DIVIDE("/", { x, y -> x / y });

}

1 个答案:

答案 0 :(得分:1)

您可以使用以下语法实现所需的功能(SAM转换):

enum class Operation private constructor(private val symbol: String, private val op: DoubleBinaryOperator) {
    PLUS("+", DoubleBinaryOperator { left, right -> left + right }),
    ...
}

请注意,这仅适用于实现Java接口,如here所述。

编辑

为进一步说明我的意见,在从Kotlin调用Java代码时,只能 使用Kotlin lambda代替功能接口(即SAM转换)。在纯Kotlin中,这是不允许的,因为您可以使用函数类型(例如,(Double, Double) -> Double来模仿DoubleBinaryOperator)。

作为示例,请考虑以下Java类:

public class MyClass {
    String append(String input, Supplier<String> supplier) {
        return input.concat(supplier.get());
    }
}

在Kotlin中,您可以像这样使用它:

val myClass = MyClass()

// Use case 1
myClass.append("something") {
    "suffix"
}

// Use case 2
myClass.append("Something", Supplier { "suffix" })

请注意,我的IDE告诉我在用例2中有一个“冗余SAM构造函数”。

现在,让我们用Kotlin重写MyClass

class MyClass {
    fun append(input: String, supplier: Supplier<String>): String {
        return input + supplier.get()
    }
}

如果我们不使用代码进行更改,则将发生用例1的编译错误:“所需的供应商,找到()->字符串”(这与您遇到的问题相同),因为SAM转换无法完成。但是,您可以使用SAM构造函数“强制”使用它(即用例2)。