如何在 .kt 中使用功能接口 class
How to use functional-interface inside .kt class
我想使用 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 });
}
您可以使用以下语法实现您想要的(SAM 转换):
enum class Operation private constructor(private val symbol: String, private val op: DoubleBinaryOperator) {
PLUS("+", DoubleBinaryOperator { left, right -> left + right }),
...
}
请注意,这仅适用于实现 Java 接口,如记录 here。
编辑
为了扩展我在下面的评论,可以使用 Kotlin lambdas 代替功能接口(所谓的 SAM 转换)仅 调用 Java 代码时科特林。这在纯 Kotlin 中是不允许的,因为您可以使用函数类型(例如,(Double, Double) -> Double
,模仿 DoubleBinaryOperator
)。
例如,考虑以下 Java class:
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 的编译错误:“Required Supplier, found () -> String”(这与您遇到的问题相同)因为无法进行 SAM 转换。但是,您可以使用 SAM 构造函数(即用例 2)“强制”它。
我想使用 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 });
}
您可以使用以下语法实现您想要的(SAM 转换):
enum class Operation private constructor(private val symbol: String, private val op: DoubleBinaryOperator) {
PLUS("+", DoubleBinaryOperator { left, right -> left + right }),
...
}
请注意,这仅适用于实现 Java 接口,如记录 here。
编辑
为了扩展我在下面的评论,可以使用 Kotlin lambdas 代替功能接口(所谓的 SAM 转换)仅 调用 Java 代码时科特林。这在纯 Kotlin 中是不允许的,因为您可以使用函数类型(例如,(Double, Double) -> Double
,模仿 DoubleBinaryOperator
)。
例如,考虑以下 Java class:
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 的编译错误:“Required Supplier, found () -> String”(这与您遇到的问题相同)因为无法进行 SAM 转换。但是,您可以使用 SAM 构造函数(即用例 2)“强制”它。