Kotlinメソッド(関数)

メソッドはfunで定義する

fun hoge1(){
    println("hoge1")
}

// 呼び出し
hoge1() // hoge1

引数ありのメソッド

fun hoge1(x: Int, y: Int){
    println("x = $x. y = $y ")
}

// 呼び出し
hoge1(5, 19) // x = 5. y = 19

戻り値、引数ありのメソッド

fun hoge1(x: Int, y: Int): Int {
    return x * y
}

// 呼び出し
println(hoge1(5, 19)) // 95

戻り値が2つの場合

Pairクラスを使う

fun hoge1(x: Int, y: Int): Pair<Int, String> {
    return (x * y) to "$x and $y"
}

// 呼び出し
val ret: Pair<Int, String> = hoge1(5, 19)
println(ret.first) // 95
println(ret.second) // 5 and 19

戻り値が3つの場合

Tripleクラスを使う

fun hoge1(x: Int, y: Int): Triple<Int, String, String> {
    return Triple(x * y , "$x and $y", "$x * $y")
}

// 呼び出し
val ret: Triple<Int, String, String> = hoge1(5, 19)
println(ret.first) // 95
println(ret.second) // 5 and 19
println(ret.third) // 5 * 19

PairやTripleはJavaApache commonsライブラリのTupleパッケージに似ている
commons.apache.org

Kotlinの場合は、下記のようにメソッド呼び出し時に型宣言を省略できる
val ret = hoge1(5, 19)

戻り値が4つの場合(Pairを組み合わせた場合)

Pairを組み合わせる

fun hoge1(x: Int, y: Int): Pair<Pair<Pair<Int, String>, Int>, String> {
    return (x * y) to "$x * $y" to (x + y) to "$x + $y"
}

// 呼び出し
val ret: Pair<Pair<Pair<Int, String>, Int>, String> = hoge1(5, 19)
println(ret.first.first.first) // 95
println(ret.first.first.second) // 5 and 19
println(ret.first.second) // 24
println(ret.second) // 5 + 19

戻り値が4つの場合(戻り値用のData Classを作成した場合)

Pairを組み合わせた場合に可読性が悪くなるので、戻り値クラスを作成する

data class Ret(val a: Int, val b: String, val c: Int, val d: String)

fun hoge1(x: Int, y: Int): Ret {
    return Ret((x * y), "$x * $y",(x + y) , "$x + $y")
}

// 呼び出し
val ret = hoge1(5, 19)
println(ret.a) // 95
println(ret.b) // 5 * 19
println(ret.c) // 24
println(ret.d) // 5 + 19

メソッド引数にNULLがある場合

引数の型の後に「?」を付ける

fun hoge1(x: Int?): Int {
    return x?.let {
        x * 10
    } ?: 0
}

// 呼び出し
println(hoge1(null)) // 0
println(hoge1(5)) // 50

関数型(Lambda)

次の例では、x、yのInt型を引数とし、戻り値にString型を定義している
val aCodeBlock: (x: Int, y: Int) -> String

実処理をブロック内に宣言する
ブロック内のx: Int, y: Int ->は宣言の引数である
実処理はif文であり、return は必要なし

(ほぼScalaと同じ書き方)

val aCodeBlock: (x: Int, y: Int) -> String = {
        if (x > y) "$x is greater than $y" else "$x is less than $y"
}

呼び出し方法は次のようになる

println(aCodeBlock(5, 3)) // 5 is greater than 3
戻り値が2つ以上

Pairなどを使用する

// 引数はx , yのInt型、戻り値はPairのInt型とString型
val bCodeBlock: (x: Int, y: Int) -> Pair<Int, String> = { x: Int, y: Int ->
    val ret1 = x * y
    val ret2: String = if (x > y) "$x is greater than $y" else "$x is less than $y"
    ret1 to ret2
}

// 呼び出し
val ret = bCodeBlock(5, 3)
println(ret.first) // 15
println(ret.second) // 5 is greater than 3
引数が1つの時はitを使用可能
val cCodeBlock:(x: Int) -> Int = {
    it * it
}

println(cCodeBlock(5)) // 25

上記は、次のようにコーディングしても同じ

val cCodeBlock: (x: Int) -> Int = { x: Int ->
    x * x
}