Kotlin: lambda nunca comstack

Acabo de empezar a aprender Kotlin y estoy teniendo un problema con la syntax lambdas allí. Hay una pequeña class de ejemplo:

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)) } } } 

La class nunca comstack porque algo está mal con lambda. Lo mismo en Java se ve así:

 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)); } } 

¿Qué debería ser corregido? Ya he intentado la conversión automática de Java en Kotlin en Intellij Idea y falló.

El problema con su código es que Kotlin no permite la conversión de SAM a las interfaces escritas en Kotlin . La razón de esta restricción es que Kotlin tiene types funcionales integrados en el lenguaje , y uno debería usarlos en su lugar (o recurrir a expresiones de objects anónimos ).

Podrías reescribir tu código para:

 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)) } } } 

Para hacer que el código sea más legible, puede usar alias de tipo :

 typealias Operation = (Int, Int) -> Int 

Si estrictamente desea traducir el código java a kotlin, la respuesta es:

 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) } 

Pero si tiene otra opción, tal vez prefiera la siguiente forma manteniendo la operación no como una interfaz como el parámetro 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) } 

Kotlin no (todavía) admite interfaces funcionales SAM para interfaces Kotlin. Solo es compatible con SAM para interfaces Java. Las razones han sido descritas en otra parte. Pero, como el paradigma SAM es omnipresente en Java, y debido a que los usuarios de Kotlin generalmente están convirtiendo Java en Kotlin, y debido a que SAM existe en gran parte de ese código para ser portado, es posible que comiencen a soportar SAM en las interfaces de Kotlin.

La respuesta (por ahora) es usar un literal de object donde se espera una conversión lambda.

 println(mathFunctions.makeCalculations(10, 20, object : Operation { override fun calculate(a:Int, b:Int):Int { return a+b } })) 

Aquí hay una discusión sobre el soporte de la function.

  • ¿Cómo funciona el generador htmlx de kotlin exactamente debajo del capó?
  • Kotlin: lambdas seguros (sin pérdida de memory)?
  • Kotlin no puede acceder a kotlin.jvm.functions.Function1 cuando llama a la function kotlin con java lambda
  • Kotlin nombró la syntax del parámetro para el cierre / lambda
  • convert comparator en lambda en Kotlin
  • Kotlin, tabla / matriz basada en inputs con campos dynamics
  • Inicializador de propiedad de múltiples líneas / complejo sin lambda
  • por qué kotlin lambda descomstackdo en código java es (Function0) null.INSTANCE
  • Referencia al método de una instancia particular en Kotlin
  • ¿Por qué la variable no se puede inicializar correctamente en la function en línea como en Java?
  • Expresiones de kotlin lambda como parámetro opcional