2017-08-31 8 views
3

私はちょうどKotlinを学び始めました。ラムダの構文に問題があります。小さなクラスがあります:Kotlin:ラムダは決してコンパイルされない

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

ラムダに何か問題があるため、クラスはコンパイルされません。 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

あなたのコードの問題は、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 
2

あなたは厳密にkotlinするためのJavaコードを変換したい場合は、答えは次のとおりです。

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

しかし、あなたは選択肢を持っている場合は、多分あなただけのインターフェースバットなどではない操作を維持することにより、以下の方法を好みますラムダパラメータ:

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

Kotlinは(まだ)Kotlinインターフェイス用のSAM機能インタフェースをサポートしていません。 。 SAM for Javaインタフェースのみをサポートしています。理由は他のところで説明されている。しかし、SAMのパラダイムはJavaでは普遍的であり、Kotlinの採用者は通常JavaをKotlinに変換しているため、移植するコードの多くにSAMが存在するため、KotlinインターフェイスでSAMをサポートする可能性があります。

答えは(今のところ)ラムダ変換が期待されるオブジェクトリテラルを使用することです。

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.

関連する問題