Kotlin:lambda永远不会编译

时间:2017-08-31 10:55:59

标签: lambda kotlin

我刚刚开始学习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,但它失败了。

3 个答案:

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

Here is a discussion on supporting the feature.