Kotlin KoansでKotlin入門 第13回:Extension functions


はじめに

公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。

過去記事はこちら

問題

Extension functions

extension functionsについて学びます。そして、extension functionsInt.r()Pair.r()を実装して、IntPairRationalNumberに変換するようにします。

Pairは標準ライブラリで定義されているクラスです

data class Pair<out A, out B>(
    val first: A,
    val second: B
)

修正前のコード

fun Int.r(): RationalNumber = TODO()

fun Pair<Int, Int>.r(): RationalNumber = TODO()

data class RationalNumber(val numerator: Int, val denominator: Int)

問題のポイント

拡張関数を宣言するには レシーバタイプ (receiver type) を関数名の前に付ける必要があります。 次の例では、 swap 関数を MutableList に追加しています:

fun MutableList<Int>.swap(index1: Int, index2: Int) {
  val tmp = this[index1] // 'this' がリストに対応する
  this[index1] = this[index2]
  this[index2] = tmp
}

拡張関数内のthisキーワードは、レシーバーオブジェクト(ドットの前に渡されるオブジェクト)に対応します。このような関数は、任意の MutableList に対して呼び出すことができます。

val list = mutableListOf(1, 2, 3)
list.swap(0, 2) // swap()' 内の 'this' は 'list' の値を保持します

この関数は、どのMutableListに対しても意味があり、汎用的に作ることができます。

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' はリストに対応する
    this[index1] = this[index2]
    this[index2] = tmp
}

解答例

fun Int.r(): RationalNumber = RationalNumber(this, 1)

fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first, second)

data class RationalNumber(val numerator: Int, val denominator: Int)