網羅的なwhen
すべてのケースを処理します
「網羅的なwhen」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。
すべてのケースを網羅する
網羅的なwhenは、考えられるすべての値を処理します。式として使用する場合、常に結果が生成されるように、Kotlinでは網羅的であることが求められます。
このレッスンでは、whenを網羅的にする方法と、その利点を学びます。
elseで網羅的にする
Intのように取り得る値が限定されていない対象では、else分岐によって列挙されていないすべてのケースを処理できます。
これにより、whenが必ず一致することが保証されます。
fun label(n: Int): String = when (n) {
0 -> "zero"
1 -> "one"
else -> "many"
}
fun main() {
println(label(0))
println(label(5))
}enumで網羅性を確保する
enumでは、コンパイラーが取り得るすべての値を把握しています。すべて列挙すれば、elseを省略できます。
enum class Direction { NORTH, SOUTH, EAST, WEST }
fun turn(d: Direction): String = when (d) {
Direction.NORTH -> "up"
Direction.SOUTH -> "down"
Direction.EAST -> "right"
Direction.WEST -> "left"
}
fun main() {
println(turn(Direction.EAST))
}enumのケースが不足している場合
式として使うwhenでenumの値を1つでも書き忘れると、コンパイラーがエラーを報告します。
これにより、新しいenum定数を追加した瞬間にバグを検出できます。
enum class Status { ACTIVE, PAUSED, STOPPED }
fun describe(s: Status): String = when (s) {
Status.ACTIVE -> "running"
Status.PAUSED -> "paused"
Status.STOPPED -> "stopped"
}
fun main() {
println(describe(Status.PAUSED))
}シールドクラス
シールドクラスには、コンパイル時に把握できる固定されたサブクラスの集合があります。
そのため、elseなしで、すべてのサブタイプを対象にwhenを網羅的にできます。
sealed class Shape
class Circle(val r: Double) : Shape()
class Square(val s: Double) : Shape()
fun area(shape: Shape): Double = when (shape) {
is Circle -> 3.14159 * shape.r * shape.r
is Square -> shape.s * shape.s
}
fun main() {
println(area(Square(4.0)))
}網羅性が役立つ理由
網羅的なwhenでは、ケースの不足が見過ごされるバグではなくコンパイルエラーになります。
新しいサブクラスやenumの値を追加すると、更新が必要なすべてのwhenをコンパイラーが指摘します。
文では網羅性を強制されない
文として(代入せずに)使う場合、whenに網羅性は求められません。
ただし、enumやシールド型では、いずれにしても網羅的にすることがよい習慣です。
enum class Light { RED, GREEN }
fun main() {
val light = Light.RED
when (light) {
Light.RED -> println("stop")
Light.GREEN -> println("go")
}
}シールドとデータを組み合わせる
シールド階層では、データクラスのサブクラスを使うことがよくあります。これにより、網羅的なマッチングと、プロパティにアクセスするためのスマートキャストの両方を利用できます。
sealed class Result
data class Ok(val value: Int) : Result()
data class Err(val message: String) : Result()
fun show(r: Result): String = when (r) {
is Ok -> "ok: " + r.value
is Err -> "error: " + r.message
}
fun main() {
println(show(Ok(42)))
println(show(Err("boom")))
}安全網としてのelse
シールド型やenumのwhenにelseを追加することもできますが、その場合、コンパイラーは新しいケースについて警告しなくなります。
elseを省略すればコンパイル時の安全性を維持できるため、クローズドな型ではその方法を優先してください。
enum class Coin { HEADS, TAILS }
fun flip(c: Coin): Int = when (c) {
Coin.HEADS -> 1
Coin.TAILS -> 0
}
fun main() {
println(flip(Coin.HEADS))
}Booleanとクローズドな対象
Booleanには2つの値しかないため、両方を列挙すればelseなしでwhenを網羅的にできます。
fun yesNo(flag: Boolean): String = when (flag) {
true -> "yes"
false -> "no"
}
fun main() {
println(yesNo(true))
println(yesNo(false))
}まとめ
網羅的なwhenでは、すべてのケースを処理します。
elseはIntのように取り得る値が限定されていない対象を処理します- enum、シールドクラス、
Booleanはelseなしで網羅的にできます - 新しいケースを追加すると、コンパイラーが不足しているケースを指摘します
sealed class Event
object Start : Event()
object Stop : Event()
fun handle(e: Event): String = when (e) {
is Start -> "starting"
is Stop -> "stopping"
}
fun main() {
println(handle(Start))
println(handle(Stop))
}理解度チェック
網羅的なwhenについての理解度を確認しましょう。
振り返り
whenを網羅的にする方法を学びました。
elseは取り得る値が限定されていない対象を処理します- enum、シールドクラス、
Booleanはすべてのケースを処理できます - コンパイル時のチェックによって、不足しているケースを検出できます
これでWhen Expressions and Smart Castsコースは完了です。
よくある質問
「網羅的なwhen」レッスンは無料ですか?
はい。「網羅的なwhen」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。
「網羅的なwhen」で何を学びますか?
すべてのケースを処理します ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Kotlin Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「網羅的なwhen」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このKotlin Academyレッスンでコードを書いて実行できますか?
はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。