Kotlinのtakeifについて

採用はこちら

takeIf は、条件を満たした場合のみそのオブジェクトを返し、条件を満たさない場合は null を返す関数です。

簡単に言うと、

条件が true  → 元のオブジェクトを返す
条件が false → null を返す

という動作をします。

定義は次のようになっています。

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T?

ポイントは次の通りです。

  • レシーバーオブジェクトに対して条件判定を行う
  • 条件を満たした場合だけそのオブジェクトを返す
  • 条件を満たさない場合は null
  • 戻り値は Nullable型(T?)
目次

基本的な使い方

もっともシンプルな例を見てみます。

val number = 10
val result = number.takeIf { it > 5 }

println(result)

結果

10

理由は、条件 10 > 5true だからです。

そのため、元の値 10 がそのまま返されます。

次に条件を満たさない場合です。

val number = 3
val result = number.takeIf { it > 5 }

println(result)

結果

null

条件が false のため、null が返ります。

if文との関係

takeIf は、次の if 文と同じ意味になります。

通常の書き方

val result = if (number > 5) number else null

takeIfを使った書き方

val result = number.takeIf { it > 5 }

このように、値を条件付きで返す処理を簡潔に書けるのが takeIf の特徴です。

ただし、条件によって 別の値を返したい場合if 文の方が自然です。

val result = if (number > 5) "OK" else "NG"

このような場合に takeIf を使うのはあまり適していません。

実装イメージ

takeIf の内部動作はとてもシンプルです。

概念的には次のような実装になっています。

inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    return if (predicate(this)) this else null
}

つまり、

  1. predicate に現在のオブジェクトを渡す
  2. 結果が true なら this を返す
  3. false なら null を返す

という処理です。

takeIflet の組み合わせ

takeIflet と組み合わせて使われることが多いです。

val number = 10

number
    .takeIf { it > 5 }
    ?.let {
        println("条件を満たしました: $it")
    }

処理の流れ

  1. takeIf で条件判定
  2. 条件が true なら値が返る
  3. ?.let により nullでない場合のみ処理が実行される

もし条件が false の場合は、

takeIf → null

となるため、let は実行されません。

実務でよくある使い方

値の範囲チェック

val validScore = score.takeIf { it in 0..100 }

0〜100の範囲に入っている場合のみ値を保持します。

文字列が空でない場合だけ使用

val text = input.takeIf { it.isNotBlank() }

空文字や空白文字列の場合は null になります。

ファイル存在チェック

val file = File("data.txt")
val validFile = file.takeIf { it.exists() }

存在するファイルだけを取得できます。

takeUnless との違い

Kotlinには takeIf と対になる関数として takeUnless があります。

takeIf

条件 true  → 値を返す
条件 false → null

takeUnless

条件 true  → null
条件 false → 値を返す

val number = 3
val result = number.takeUnless { it > 5 }

println(result)

結果

3

条件が true の場合は null になり、false の場合は値が返されます。

takeIf を使うときの注意点

値の生成自体は防げない

次のようなコードには注意が必要です。

val result = createExpensiveObject().takeIf { it.isValid() }

この場合、isValid() が false でも

createExpensiveObject()

先に実行されます

つまり takeIf

条件を満たすときだけ生成する

関数ではありません。

あくまで

すでにある値を条件で残すかどうか判断する

関数です。

単純な条件分岐では if の方が読みやすいこともある

例えば次のコードです。

user.takeIf { it.age >= 20 }
    ?.drinkBeer()

これは文法的には正しいですが、次のコードの方が読みやすいと感じる場合も多いです。

if (user.age >= 20) {
    user.drinkBeer()
}

takeIf は便利ですが、すべての条件分岐を置き換えるものではありません。

takeIf を使うべき場面

takeIf が特に役立つのは次のようなケースです。

  • 値を条件付きで残したい
  • null安全と組み合わせたい
  • メソッドチェーンの途中で条件を入れたい

val result =
    input
        .trim()
        .takeIf { it.isNotEmpty() }
        ?.uppercase()

このように 処理チェーンの中に条件を自然に組み込めるのが takeIf の大きな利点です。

まとめ

takeIf は、オブジェクトに条件を適用し、

条件 true  → 元の値を返す
条件 false → null

という動作をする関数です。

主な特徴

  • if (condition) value else null を簡潔に書ける
  • let などと組み合わせて null安全な処理を書ける
  • 処理チェーンの途中に条件を入れられる

ただし、

  • 値の生成自体を抑制するわけではない
  • 単純な条件分岐では if の方が読みやすいこともある

という点には注意が必要です。

以上、Kotlinのtakeifについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次