はじめに
こんにちは、suzukiです。
今更ながらKotlinの学習を初めました。iOSの開発がメインのため、Androidのことに関しては無知のためわからないことだらけです。
本を読みながら学習中で、備忘のためこちらで記事にしていこうと思います。
今回はスコープ関数についてです。
スコープ関数とは
Kotlinではスコープ関数と呼ばれる関数群が用意されています。これらは特定の名前で参照される範囲を変更し
- コードの簡略化
- コードの可読性を上げる
上記を目的に使われます。必ず使わなくてはならないかというとそんなことはないらしいのですが、Kotlinの魅力の一つだと思い学んで行きたいと思います。
スコープ関数の種類について
今回説明するスコープ関数を先にあげます。
スコープ関数 | 書式 | アクセス方法 | 戻り値 |
with | with(関数オブジェクト){処理} | this | ラムダの戻り値 |
apply | 対象オブジェクト.apply{処理} | this | 対象オブジェクト |
let | 対象オブジェクト.let{処理} | it | ラムダの戻り値 |
run | 対象オブジェクト.run{処理} | this | ラムダの戻り値 |
以上合計4つです。
with関数
with関数は対象のオブジェクトに対して繰り返し処理を行う場合に使います。
ラムダ式内ではthisで参照し、ラムダ式の戻り値を返します。
with(関数オブジェクト){処理}
使い方
仮に下記のようなクラスがある場合
1 2 3 4 5 6 7 | //Student class Student(val name: String){ var grade : Int = 0 fun say(): String { return "$grade 年 , $name " } } |
withを使わない場合
1 2 3 | val sato = Student("sato") sato.grade = 2 println(sato.say()) |
withを使う場合
1 2 3 4 5 6 7 | val suzuki = with(Student("suzuki")){ //thisは省略可能 grade = 1 //最後に評価された値が返却される。say()を最後に記述すればラムダの戻り値はString this } println(suzuki.say()) |
所感
インスタンスを省略してアクセスできるため描きやすい、また特定の関数の戻り値だけ必要な場合などに便利に使えそう。
thisでインスタンスを返すのであれば後述のapplyを使った方がいい気がする。
冗長になるかもしれないが戻り値の型を書くなどのルールが欲しくなるかもしれない。
apply関数
オブジェクトを生成してそこに各種設定値を渡す場合によく使用される。withと似ているが戻り値が対象オブジェクトである。
対象オブジェクト.apply{処理}
使い方
先ほどのStudentクラスでapplyを使用する場合
1 2 3 4 | val sato = Student("sato").apply{ // thisは省略可能 grade = 2 }//.でアクセスすることも可能 |
所感
戻り値が対象オブジェクトなので、結果がわかりやすい。
withとの使いわけは対象オブジェクトをそのまま使いたいときはapplyを使う程度の使いわけでいい気がする。
let関数
letはnull許容型を?.と一緒に使うことで扱いやすくすることができる。対象オブジェクトをitで参照できラムダ式の戻り値がletの戻り値になる。
対象オブジェクト.let{処理}
使い方
?.でnull評価+ラムダ内で処理を行い結果を返却という使われ方が多い。
1 2 3 4 5 | var suzuki: String? = "suzuki" var upperCase = suzuki?.let { it.toUpperCase() } println(upperCase) |
所感
?.の機能で対象のオブジェクトのnull評価+何らかの処理を行うためflatMapのような使い方ができそう。
ラムダの結果は特に意識せずにswiftのif let みたいな使い方もできる。
後述のrunと比較した場合、thisがスコープ内とスコープ外で同じという点が大きく違う。
run関数
letとほぼほぼ同じだがwithやapplyのようにthisで対象のオブジェクトにアクセスが可能。
使い方
thisで参照できるようになっているため、レシーバーに対する処理になる。?:で使う場合はthisの内容はスコープの内外で同じになる。。。
1 2 3 4 5 6 | var suzuki: String? = "suzuki" var upperCase = suzuki?.run { //thisで参照できるため省略可能 toUpperCase() } println(upperCase) |
所感
runという名前から何らかの処理を行い結果を返すという考え方で、レシーバーがnullだった時に何らかの処理を行って値を取得するという使い方であればletとの使いわけがしやすいかと思える。
さいごに
他にもスコープ関数はあるのですが、学習中の本で扱われているのは上記の4つでした。
それぞれまとめてみると、スコープ関数の使用するルールを決めて運用していく方がいいように感じました。
letであれば全部のパターンに使えそうですし、、、
KotlinはSwiftと似ているということで勧められて勉強しておりますが、iOSとAndroidの違いで苦戦しております。