I've just started learning Kotlin and I'm having a problem with lambdas syntax there. There is a small example class:
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))
}
}
}
The class never compiles because something is wrong with lambda. The same in Java looks like this:
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));
}
}
What should be corrected? I've already tried automatic conversion from Java into Kotlin in Intellij Idea and it failed.
The problem with your code is that Kotlin does not allow SAM conversion to interfaces written in Kotlin. The reason for this restriction is that Kotlin has functional types built into the language, and one should use them instead (or fall back to anonymous object expressions).
You could rewrite your code to:
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))
}
}
}
To make the code more readable, you can use type aliases:
typealias Operation = (Int, Int) -> Int
If you strictly want to translate the java code to kotlin, the answer is:
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)
}
But if you have a choice, maybe you prefer the following way by keeping the operation not as interface bat just as lambda parameter:
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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With