【Kotlin】関数オブジェクトとは?::関数名(リファレンス)と高階関数について
この記事からわかること
- Android Studio/Kotlinの関数オブジェクトとは?
- ::関数名記法の使い方
- 高階関数や関数リファレンスなどの意味
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
Kotlinでは関数を引数に渡したり、返り値として関数を返すことが可能です。これによりコードの再利用や抽象化、拡張性の向上などさまざまなメリットが生まれています。実際にKotlinで関数をオブジェクトとして扱う方法についてまとめていきたいと思います。
Kotlinの関数オブジェクトとは?
Kotlinの関数オブジェクトを理解するためにはまず「第一級オブジェクト」と呼ばれる概念を理解する必要があります。Kotlinに限らずですがプログラミング言語では変数に代入したり、関数の引数や返り値に指定できるオブジェクトのことを第一級オブジェクトと呼びます。これは整数や文字列、独自のクラスなども第一級オブジェクトに当たります。
Kotlinではその第一級オブジェクトに関数も含まれます。なので関数を変数に代入したり、他の関数の引数として関数を渡したり、別の関数を返り値として指定するといったオブジェクトと同じような扱いが可能になっています。
実装してみる
関数オブジェクトを生成するためにはラムダ式(クロージャー)や無名関数、後述する関数リファレンスを使用します。変数のデータ型を指定する際は(Int) -> Int
のように引数に受け取るデータ型と返り値となるデータ型を指定します。何も返さない場合はUnit
を指定します。
val add1: (Int) -> Int = { x -> x + 1 } // ラムダ式
val add2: (Int) -> Int = fun(x: Int): Int = x + 2 // 無名関数
val addPrint: (Int, Int) -> Unit = { x, y -> // 引数2つ、返り値なし
val sum = x + y
print(sum.toString())
}
ラムダ式では最後に評価した式が返り値になるのでreturn
などを明示的に記述する必要はありません。
関数オブジェクトを生成しただけでは、関数は実行されません。そのまま出力してみると関数自体の内容が出力されることを確認できます。
// 関数(ラムダ式)を変数に代入する ここでは実行はされない
val add: (Int, Int) -> Int = { x, y -> x + y }
// 関数オブジェクトを出力
println(add) // Function2<java.lang.Integer, java.lang.Integer, java.lang.Integer>
変数に格納した関数オブジェクトを実行するためにはinvoke
メソッドを使用して実行する必要があります。invoke
メソッドはシンタックスシュガー(=ある構文を別の記法で記述できるようにしたもの)として省略することができるので、add(3, 5)
と記述しても正常に動作します。
// 関数(ラムダ式)を変数に代入する
val add: (Int, Int) -> Int = { x, y -> x + y }
// invokeメソッドで実行する
println(add.invoke(3, 5)) // 出力:8
// 変数を通じて関数を呼び出す
val result = add(3, 5) // add.invoke(3.5)のシンタックスシュガー
println("3 + 5 = $result") // 出力:3 + 5 = 8
高階関数とは?
fun main() {
// 関数(ラムダ式)を変数に代入する
val add: (Int, Int) -> Int = { x, y -> x + y }
// 関数を他の関数の引数として渡す
val executeResult = execute(7, 2, add)
println("7 + 2 = $executeResult") // 出力:7 + 2 = 9
}
// 関数を引数として受け取り、その関数を使って計算を行う関数(高階関数)
fun execute(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
}
execute
関数は引数に(Int, Int) -> Int
型の関数を受け取り、内部でそれを実行する関数で、このように引数として関数を受け取ったり、また関数自体が返り値となっている関数のことを「高階関数」と呼びます。
高階関数の条件
- 引数として関数を受け取る関数
- 関数自体が返り値となっている関数
よく使用されている高階関数で言うとmap
やfilter
、forEach
などが該当すると思います。
関数リファレンス
ここまではSwiftなどでも同じ言語使用なので理解しやすいかと思いますが、Kotlinでは関数リファレンス(関数参照)と呼ばれる仕組みが用意されています。関数リファレンス(関数参照)は関数をオブジェクトとして取得するための仕組みで::
演算子を使用して関数オブジェクトを作成します。
fun add(x: Int, y: Int): Int {
return x + y
}
val functionReference = ::add // 関数リファレンスで関数オブジェクトを取得
またクラスのメンバ関数も関数リファレンスを使用して取得することが可能です。
class MyClass {
fun add(x: Int, y: Int): Int {
return x + y
}
}
val instance = MyClass()
val memberFunctionReference = instance::add
参考文献:Kotlin:関数オブジェクト
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。