[毎日Kotlin] Day12. SAM conversions(SAM変換)

2018.01.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

毎日Kotlinシリーズです。

このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO

問題

SAM conversions | Try Kotlin

前回object式で書いていた部分を、SAM変換で書いてみよう。JavaコードをKotlinから呼ぶ時に楽になります。

When an object implements a SAM interface (one with a Single Abstract Method), you can pass a lambda instead. Read more about SAM-conversions.

In the previous example change an object expression to a lambda.

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> TODO() })
    return arrayList
}

狙い

ここで考えて欲しい問題の意図はなんだろうか?

[毎日Kotlin] Day11. Object expressions(オブジェクト式)では、object式で無名クラスを作りました。

JavaコードをKotlinから呼ぶ場合、Abstractメソッドが1つのクラスを作る場合は、ラムダ式でかける便利機能があります。Koltinの場合はSAM変換ができません。なぜなら、最初からそういうコードを書ける機能があるから。

Calling Java from Kotlin - Kotlin Programming Language

Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

解答例

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y - x })
    return arrayList
}

[毎日Kotlin] Day11. Object expressions(オブジェクト式)のobject式の解答と比較してみよう。

import java.util.*
 
fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object : Comparator<Int> {
        override fun compare(x: Int, y: Int) = y - x
    })
    return arrayList
}

メソッドが1つしかない場合に限定してるので、overrideするメソッド名を書く必要もなく、変数の個数と型があっていれば使えます。引数の個数だけあっていれば、型も省略可能。引数が1つの時は、itがデフォルトの引数名でつかえるので省略可能です。とても便利ですね。

[毎日Kotlin] Day5.Lambdas(ラムダ式) から、少し変えてます。

Androidの例

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.v(TAG, v.getId() + "clicked");
    }
});

View.OnClickListener(v: View) -> Unitのラムダと同じとみれる(SAM変換)。

button.setOnClickListener { Log.v(TAG, "${it.id} clicked") }

メソッドが2つ以上ある場合はobject式を使いましょう。

あとがき

Day13.でまたお会いしましょう。