我刚刚开始学习Kotlin,我在那里遇到lambda语法问题。有一个小例子类:
class MathFunctions {
@FunctionalInterface
interface Operation {
fun calculate(a: Int, b: Int): Int
}
fun makeCalculations(a: Int, b: Int, operation: Operation): Int = operation.calculate(a, b)
companion object {
@JvmStatic
fun main(args: Array<String>) {
val plus = Operation { a, b -> a + b }
val mathFunctions = MathFunctions()
println(mathFunctions.makeCalculations(10, 20, plus))
}
}
}
该类从不编译,因为lambda出了问题。 Java中的相同内容如下:
public class MathFunctions {
@FunctionalInterface
interface Operation {
int calculate(int a, int b);
}
public int makeCalculations(int a, int b, Operation operation) {
return operation.calculate(a, b);
}
public static void main(String[] args) {
Operation plus = (a, b) -> a + b;
MathFunctions example = new MathFunctions();
System.out.println(example.makeCalculations(10, 20, plus));
}
}
应该纠正什么?我已经尝试过在Intellij Idea中从Java自动转换到Kotlin,但它失败了。
答案 0 :(得分:3)
您的代码存在的问题是Kotlin does not allow SAM conversion to interfaces written in Kotlin。这种限制的原因是Kotlin有functional types built into the language,而且应该使用它们(或者回到anonymous object expressions)。
您可以将代码重写为:
class MathFunctions {
fun makeCalculations(a: Int, b: Int, operation: (Int, Int) -> Int): Int =
operation(a, b)
companion object {
@JvmStatic
fun main(args: Array<String>) {
val plus: (Int, Int) -> Int = { a, b -> a + b }
val mathFunctions = MathFunctions()
println(mathFunctions.makeCalculations(10, 20, plus))
}
}
}
为了使代码更具可读性,您可以使用type aliases:
typealias Operation = (Int, Int) -> Int
答案 1 :(得分:2)
如果您严格要将java代码翻译为kotlin,答案是:
fun main(args: Array<String>) {
val plus = object : MathFunctions.Operation {
override fun calculate(a: Int, b: Int) = a + b
}
val mathFunctions = MathFunctions()
println(mathFunctions.makeCalculations(10, 20, plus))
}
class MathFunctions {
@FunctionalInterface
interface Operation {
fun calculate(a: Int, b: Int): Int
}
fun makeCalculations(a: Int, b: Int, operation: Operation): Int = operation.calculate(a, b)
}
但是如果你有一个选择,也许你更喜欢以下方式:将操作保持为接口bat而不是lambda参数:
fun main(args: Array<String>) {
val mathFunctions = MathFunctions()
println(mathFunctions.makeCalculations(10, 20, { a, b -> a + b}))
}
class MathFunctions {
fun makeCalculations(a: Int, b: Int, operation: (Int, Int) -> Int): Int = operation(a, b)
}
答案 2 :(得分:1)
Kotlin(尚未)支持Kotlin接口的SAM功能接口。它仅支持SAM for Java Interfaces。原因已在别处描述。但是,因为SAM范例在Java中无处不在,并且因为Kotlin采用者通常将Java转换为Kotlin,并且因为SAM存在于要移植的大部分代码中,所以他们可能会开始在Kotlin接口上支持SAM。 p>
答案(目前)是使用希望进行lambda转换的对象文字。
println(mathFunctions.makeCalculations(10, 20, object : Operation {
override fun calculate(a:Int, b:Int):Int {
return a+b
}
}))