📝

Result (sealed class)

に公開

はじめに

sealed class をついさっき初めて知ったのですが、さらに
Kotlin標準ライブラリのResultを活用したエラーハンドリング ... も知らず...
今回(自分のために)記事にしました。


Resultとは?

Result は Kotlin 標準ライブラリで提供される型で、成功と失敗を安全に扱うための仕組みです。非同期処理やエラーハンドリングを簡潔かつ型安全に記述できるため、多くの場面で活用できます。


Resultの特徴

  • 成功 (Success)失敗 (Failure) を1つの型で表現できる。
  • 型安全であり、例外を安全にカプセル化できる。
  • Kotlin 1.3 以降で利用可能。
  • 主に関数の戻り値として使用される。

基本的な使い方

成功と失敗を返す関数

Result.successResult.failure を使って、関数の戻り値を明確に表現します。

fun divide(a: Int, b: Int): Result<Int> {
    return if (b != 0) {
        Result.success(a / b)
    } else {
        Result.failure(IllegalArgumentException("Divider can't be zero"))
    }
}

呼び出し例

成功と失敗を簡単に処理できます。

val result = divide(4, 2)
result.fold(
    onSuccess = { println("Result: $it") },
    onFailure = { println("Error: ${it.message}") }
)

主なメソッド

1. fold

成功時と失敗時の処理をそれぞれ指定できます。

result.fold(
    onSuccess = { println("Success: $it") },
    onFailure = { println("Failure: ${it.message}") }
)

2. getOrNull

成功時は値を返し、失敗時は null を返します。

val value = result.getOrNull()
println(value) // 成功: 結果を表示。失敗: null。

3. exceptionOrNull

失敗時の例外を取得できます。

val exception = result.exceptionOrNull()
println(exception?.message) // 成功: null。失敗: 例外のメッセージ。

4. map

成功時の値を変換します。

val mappedResult = result.map { it * 2 }
println(mappedResult.getOrNull()) // 成功: 値を変換後に表示。失敗: null。

5. mapCatching

変換中に例外が発生する可能性がある場合に使用します。

val safeMappedResult = result.mapCatching { it / 0 }
safeMappedResult.fold(
    onSuccess = { println("Result: $it") },
    onFailure = { println("Error: ${it.message}") }
)

実用例

1. 簡単なエラーハンドリング

Result を使って、例外を明確に処理できます。

fun fetchDataFromServer(): Result<String> {
    return try {
        Result.success("Data fetched successfully")
    } catch (e: Exception) {
        Result.failure(e)
    }
}

val result = fetchDataFromServer()
result.fold(
    onSuccess = { println(it) },
    onFailure = { println("Error: ${it.message}") }
)

2. リトライ処理

複数回の試行で成功を得る例です。

fun retryableOperation(): Result<Int> {
    return try {
        val value = (1..10).random()
        if (value > 5) Result.success(value) else throw RuntimeException("Value too low")
    } catch (e: Exception) {
        Result.failure(e)
    }
}

val retryResult = (1..3).asSequence()
    .map { retryableOperation() }
    .first { it.isSuccess }

println(retryResult.getOrNull())

Resultを使うメリット

コードの簡潔化:
成功と失敗のハンドリングを1つの型で表現できるため、複雑なエラーチェックが不要。


まとめ

Kotlin 標準ライブラリの Result を使うことで、成功と失敗を安全かつ簡潔に扱うことができます。

例外処理や非同期コードでその真価を発揮するらしい(今回未確認)ので、どんどん使って知見を深めたいです。

この便利な Result を使って、よりメンテナブルなコードを書けるように頑張ります。


参考URL

Discussion