SealedなResult階層
カスタムの結果型を作成します
「SealedなResult階層」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。
組み込みResultの先へ
Kotlinの Result は、失敗時に例外しか保持できません。より豊富で型付けされたエラー情報が必要になることもよくあります。sealed class の階層を使うと、ドメインに存在する結果を正確にモデル化できます。
sealedな結果
成功とエラーのサブクラスを持つ sealed 型を定義します。コンパイラーはすべてのケースを把握できるため、網羅的な処理が可能になります。
sealed class Outcome<out T> {
data class Ok<T>(val value: T) : Outcome<T>()
data class Err(val message: String) : Outcome<Nothing>()
}
fun main() {
val r: Outcome<Int> = Outcome.Ok(5)
println(r)
}網羅的なwhen
型が sealed なので、その型に対する when では else が不要です。コンパイラーがすべてのケースを処理していることを保証します。
sealed class Outcome<out T> {
data class Ok<T>(val value: T) : Outcome<T>()
data class Err(val message: String) : Outcome<Nothing>()
}
fun describe(o: Outcome<Int>) = when (o) {
is Outcome.Ok -> "value " + o.value
is Outcome.Err -> "error " + o.message
}
fun main() {
println(describe(Outcome.Ok(9)))
println(describe(Outcome.Err("boom")))
}型付きエラーのバリエーション
異なる種類の失敗を別々のサブクラスとしてモデル化し、それぞれに関連するデータを保持させます。1つの不透明な例外にまとめるよりも優れた方法です。
sealed class Fetch<out T> {
data class Success<T>(val data: T) : Fetch<T>()
data class NotFound(val id: Int) : Fetch<Nothing>()
data class Network(val code: Int) : Fetch<Nothing>()
}
fun main() {
val r: Fetch<String> = Fetch.NotFound(42)
println(r)
}各バリエーションの処理
when を使うと、各エラー型に応じた処理を行えます。それぞれの分岐で、必要なデータをすべて利用できます。
sealed class Fetch<out T> {
data class Success<T>(val data: T) : Fetch<T>()
data class NotFound(val id: Int) : Fetch<Nothing>()
data class Network(val code: Int) : Fetch<Nothing>()
}
fun handle(f: Fetch<String>) = when (f) {
is Fetch.Success -> "data: " + f.data
is Fetch.NotFound -> "missing id " + f.id
is Fetch.Network -> "net error " + f.code
}
fun main() {
println(handle(Fetch.Network(503)))
}Nothingのテクニック
成功値を持たないエラーバリエーションには、Outcome<Nothing> を使用します。Nothing はすべての型のサブタイプであり、ジェネリック型が out なので、エラーを任意の Outcome<T> に適合させられます。
sealed class Res<out T> {
data class Ok<T>(val v: T) : Res<T>()
object Empty : Res<Nothing>()
}
fun get(flag: Boolean): Res<String> =
if (flag) Res.Ok("hi") else Res.Empty
fun main() {
println(get(false))
}状態を持たないケースのobject
エラーバリエーションがデータを持たない場合は、クラスではなく object のシングルトンとして宣言します。
sealed class Login {
data class Success(val user: String) : Login()
object WrongPassword : Login()
object Locked : Login()
}
fun main() {
val r: Login = Login.WrongPassword
println(r === Login.WrongPassword)
}階層を返す
関数が sealed 型を返すようにすると、呼び出し側はすべての結果に対応する必要があるため、エラーパスの処理漏れをなくせます。
sealed class Parsed {
data class Num(val value: Int) : Parsed()
data class Bad(val input: String) : Parsed()
}
fun parse(s: String): Parsed {
val n = s.toIntOrNull()
return if (n != null) Parsed.Num(n) else Parsed.Bad(s)
}
fun main() {
when (val r = parse("x")) {
is Parsed.Num -> println(r.value)
is Parsed.Bad -> println("bad: " + r.input)
}
}sealed型と組み込みResultの比較
すばやく例外ベースの捕捉を行う場合は、組み込みの Result を使用します。ドメイン固有のデータを持つ複数の型付きエラーケースと、網羅的な処理が必要な場合は、独自の sealed 階層を使用します。
階層の設計
よい sealed result の設計は次のとおりです。
- ペイロードを保持する成功バリエーションを1つ用意する
- 意味のある失敗の種類ごとにサブクラスを1つ用意する
- エラーのみのケースには
out Tの変性とNothingを使用する
安全網としてのコンパイラー
最大の利点は、後から新しいバリエーションを追加したときに、網羅的でない when がすべてコンパイルエラーになることです。対応が必要な場所を1つずつ示してくれるため、エラーが気付かないうちに通り抜けることはありません。
理解度チェック
sealed result 階層についての理解度を確認しましょう。
まとめ
sealed result 階層を構築しました。
- 成功と型付きエラーのバリエーション
elseを使わない網羅的なwhen- エラーのみのケースに対応する
out TとNothing - 新しいバリエーションの処理をコンパイラーが保証する仕組み
次は、map と recover を使った関数型エラー処理です。
AI チューターと学ぶ Kotlin — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 51
- レッスン
- 203
よくある質問
「SealedなResult階層」レッスンは無料ですか?
はい。「SealedなResult階層」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。
「SealedなResult階層」で何を学びますか?
カスタムの結果型を作成します ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Kotlin Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「SealedなResult階層」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このKotlin Academyレッスンでコードを書いて実行できますか?
はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Result型
- runCatching
- SealedなResult階層
- 関数型エラーハンドリング