guard letとif let
KotlinにSwiftにあるようなguard let
とif let
が欲しいときのサンプルです。
また、この記事で検証したKotlinのversionは1.3.72
です。
guard let is 何?
引数のいずれかにnullがあると処理を実行する。
早期リターンとかでよく使います。
if let is 何?
引数すべてがnullではなかった時に処理を実行する。
ソースコード
StackOverflowより引用しました。
extendedLet.kt
package hogehoge.common
inline fun <T: Any> guardLet(vararg elements: T?, closure: () -> Nothing): List<T> {
return if (elements.all { it != null }) {
elements.filterNotNull()
} else {
closure()
}
}
inline fun <T: Any> ifLet(vararg elements: T?, closure: (List<T>) -> Unit) {
if (elements.all { it != null }) {
closure(elements.filterNotNull())
}
}
備考その1
Kotlinはクラスやオブジェクトでなくても直接関数を定義できるのでcommon
パッケージ的なものを作成して
extendedLet.kt
みたいなファイルを作って入れておけばそのプロジェクト全体で使えるようになるので便利です(依存/結合度気にしなければ)。
実際に使用するときは
import hogehoge.common.ifLet
import hogehoge.common.guardLet
// example
fun guardLetSample(var1 : Float?, var2 : Float?, var3 : Float?) {
// var1,var2,var3いずれかがnullなら早期リターンする
// 戻り値のvar1, var2, var3はアンラップされている
val (var1, var2, var3) = guardLet(var1, var2, var3){ return }
// 本来の処理
}
fun ifLetSample(var1 : Float?, var2 : Float?, var3 : Float?) {
ifLet(var1, var2, var3){ (var1, var2, var3) ->
// var1, var2, var3いずれもnullでないなら実行する処理
// var1, var2, var3はアンラップされている
}
}
みたいな感じでimportしてあげればいいんじゃないかと思います。
備考その2
ifLetの要素が6個以上になるとDestructuring declaration initializer of type List<Float> must have a 'component6()' function
とかいって怒られる。
extendedDestructingDeclations.kt
package hogehoge.common
// Destructuring Declarations - Kotlinはcomponent5までしか用意してないので6以降は自作する必要がある?
operator fun <E> List<E>.component6(): E {
return this[5]
}
この記事によると、この呼び出しはDestructuring Declarations
という仕組みで行われていて、
Collectionクラスではcomponent5までしかpredefineされていないとのこと(実際エラーで怒られた)。
なので、同様にcomponent6以降の関数を自作する必要があるみたいです。
また実際に使用するときは下記のようにimportしてあげないとダメです。
import hogehoge.common.component6