Kotlin when
式入門:switch文の代替と直接出力の実践
Kotlinのwhen
式は、従来のswitch
文を置き換えるだけでなく、より強力で柔軟な制御フローを記述するための機能を提供します。この記事では、when
式の基本的な構文から、様々な活用例、そして直接出力の実践までを網羅的に解説します。
1. when
式とは?:Kotlinにおける条件分岐の進化
when
式は、Kotlinにおける条件分岐の中核を担う機能です。Javaなどの言語におけるswitch
文と似た役割を果たしますが、その機能は比較対象の値の一致判定に留まりません。when
式は、より複雑な条件式、型の判定、範囲指定など、多様な条件分岐を簡潔に記述することができます。
1.1 switch
文との比較:簡潔性と表現力の向上
従来のswitch
文と比較して、when
式は以下のような点で優れています。
- 暗黙的な
break
:switch
文では、各case
の最後にbreak
文を記述しないと、意図しないフォールスルーが発生する可能性があります。when
式では、条件に一致した場合、そのブロックのみが実行され、暗黙的に処理が終了します。 - 柔軟な条件:
when
式では、単なる値の一致だけでなく、より複雑な条件式を使用できます。例えば、範囲指定、型の判定、真偽値による判定などが可能です。 - 式としての評価:
when
式は値を返す式として扱うことができます。これにより、条件分岐の結果を変数に代入したり、関数の戻り値として直接使用したりすることが可能です。 - 可読性の向上:
when
式は、より簡潔で読みやすいコードを記述できるように設計されています。
1.2 when
式の基本的な構文
when
式の基本的な構文は以下の通りです。
kotlin
when (expression) {
value1 -> {
// value1とexpressionが一致した場合の処理
}
value2 -> {
// value2とexpressionが一致した場合の処理
}
...
else -> {
// どの条件にも一致しない場合の処理 (省略可能)
}
}
expression
: 評価する式。この式の値が各条件と比較されます。value1
,value2
, …:expression
と比較される値または条件式。->
: 条件と処理を区切る記号。{ ... }
: 条件が一致した場合に実行されるコードブロック。ブロックが単一の式である場合は、{}
を省略できます。else
: どの条件にも一致しない場合に実行されるコードブロック。else
ブロックは省略可能です。
2. when
式の様々な活用例:条件分岐の強力な武器
when
式は、様々な条件分岐のシナリオで活用できます。ここでは、具体的な例を挙げながら、when
式の多様な使い方を解説します。
2.1 値の一致判定:基本的な使い方
最も基本的な使い方は、特定の値との一致判定です。
“`kotlin
fun describe(obj: Any): String =
when (obj) {
1 -> “One”
“Hello” -> “Greeting”
is Long -> “Long”
!is String -> “Not a string”
else -> “Unknown”
}
println(describe(1)) // 出力: One
println(describe(“Hello”)) // 出力: Greeting
println(describe(1000L)) // 出力: Long
println(describe(2.3)) // 出力: Not a string
println(describe(listOf(1,2))) // 出力: Unknown
“`
この例では、when
式は、obj
の値に応じて異なる文字列を返しています。
1
との一致判定"Hello"
との一致判定is Long
:obj
がLong
型であるかの判定!is String
:obj
がString
型でないかの判定else
:上記のいずれにも一致しない場合の処理
2.2 複数の条件をまとめて記述:カンマ区切りで簡潔に
複数の条件に対して同じ処理を実行したい場合は、カンマで区切って条件を記述できます。
“`kotlin
fun eval(number: Int): String {
return when (number) {
0, 1 -> “Zero or One”
in 2..10 -> “Between 2 and 10”
else -> “Other”
}
}
println(eval(0)) // 出力: Zero or One
println(eval(5)) // 出力: Between 2 and 10
println(eval(15)) // 出力: Other
“`
この例では、number
が0
または1
の場合、”Zero or One”を返します。
2.3 範囲指定:in
演算子を使ってスマートに
in
演算子を使うと、値が特定の範囲に含まれるかどうかを判定できます。
“`kotlin
fun checkNumber(x: Int) {
when (x) {
in 1..10 -> println(“x is in the range 1..10”)
in 11..20 -> println(“x is in the range 11..20”)
!in 1..10 -> println(“x is outside the range 1..10”)
else -> println(“none of the above”)
}
}
checkNumber(5) // 出力: x is in the range 1..10
checkNumber(15) // 出力: x is in the range 11..20
checkNumber(25) // 出力: x is outside the range 1..10
“`
この例では、x
の値が1..10
または11..20
の範囲に含まれるかどうかを判定しています。!in
演算子を使うと、範囲外にあるかどうかを判定できます。
2.4 型の判定:is
演算子で安全なキャスト
is
演算子を使うと、変数の型を判定し、安全にキャストできます。
“`kotlin
fun smartCast(obj: Any): String {
return when (obj) {
is String -> “Length: ${obj.length}” // obj is smart-casted to String
is Int -> “Value: ${obj + 1}” // obj is smart-casted to Int
else -> “Unknown type”
}
}
println(smartCast(“Kotlin”)) // 出力: Length: 6
println(smartCast(10)) // 出力: Value: 11
println(smartCast(true)) // 出力: Unknown type
“`
この例では、obj
がString
型の場合、obj.length
にアクセスできます。これは、obj
がString
型であることがwhen
式によって保証されているため、コンパイラが自動的にスマートキャストを行うためです。
2.5 条件式を直接記述:when
引数を省略してより柔軟に
when
式は、引数を省略して、条件式を直接記述することもできます。この場合、各条件は真偽値を返す式である必要があります。
“`kotlin
fun isPositive(number: Int): String {
return when {
number > 0 -> “Positive”
number < 0 -> “Negative”
else -> “Zero”
}
}
println(isPositive(5)) // 出力: Positive
println(isPositive(-5)) // 出力: Negative
println(isPositive(0)) // 出力: Zero
“`
この例では、when
式は、number
が正、負、ゼロのいずれであるかを判定しています。when
引数を省略することで、より複雑な条件式を記述しやすくなります。
2.6 when
式を式として使用:簡潔なコードの実現
when
式は値を返す式として扱うことができます。これにより、条件分岐の結果を変数に代入したり、関数の戻り値として直接使用したりすることが可能です。
“`kotlin
fun getGrade(score: Int): Char {
return when (score) {
in 90..100 -> ‘A’
in 80..89 -> ‘B’
in 70..79 -> ‘C’
in 60..69 -> ‘D’
else -> ‘F’
}
}
val grade = getGrade(85)
println(“Grade: $grade”) // 出力: Grade: B
“`
この例では、getGrade
関数は、when
式を使ってスコアに応じて成績を判定し、その結果を返しています。when
式が値を返すため、変数grade
に直接代入できます。
3. when
式とelse
:網羅性の重要性
when
式を式として使用する場合、コンパイラは網羅性をチェックします。つまり、すべての可能なケースを網羅しているかどうかを確認します。もし網羅されていない場合、コンパイルエラーが発生します。
“`kotlin
enum class Color {
RED, GREEN, BLUE
}
fun getColorName(color: Color): String {
return when (color) {
Color.RED -> “Red”
Color.GREEN -> “Green”
// Color.BLUEがないため、コンパイルエラーが発生する
}
}
“`
この例では、Color
enumのすべてのケースを網羅していないため、コンパイルエラーが発生します。この問題を解決するには、else
ブロックを追加するか、すべてのケースを明示的に記述する必要があります。
“`kotlin
enum class Color {
RED, GREEN, BLUE
}
fun getColorName(color: Color): String {
return when (color) {
Color.RED -> “Red”
Color.GREEN -> “Green”
Color.BLUE -> “Blue” // すべてのケースを網羅
}
}
// または
fun getColorName(color: Color): String {
return when (color) {
Color.RED -> “Red”
Color.GREEN -> “Green”
else -> “Unknown” // elseブロックを追加
}
}
“`
else
ブロックは、予期しない値が発生した場合の安全策として役立ちます。
4. when
式による直接出力:簡潔なデバッグとログ出力
when
式は、直接出力を伴う処理にも活用できます。デバッグやログ出力などの場面で、条件に応じて異なるメッセージを出力する際に便利です。
“`kotlin
fun logEvent(eventCode: Int) {
when (eventCode) {
100 -> println(“Event: User logged in”)
200 -> println(“Event: Item purchased”)
300 -> println(“Event: Payment failed”)
else -> println(“Event: Unknown event code ($eventCode)”)
}
}
logEvent(100) // 出力: Event: User logged in
logEvent(250) // 出力: Event: Unknown event code (250)
“`
この例では、logEvent
関数は、イベントコードに応じて異なるログメッセージを出力しています。when
式を使うことで、条件分岐と出力処理を簡潔に記述できます。
5. 実践的な例:状態管理とUI制御への応用
when
式は、状態管理やUI制御など、より複雑なシナリオでも効果を発揮します。
5.1 状態管理:状態遷移をスマートに記述
“`kotlin
enum class State {
IDLE, LOADING, SUCCESS, ERROR
}
class UIController {
private var state: State = State.IDLE
fun updateUI() {
when (state) {
State.IDLE -> {
// UIを初期状態に設定
println("UI: Idle state")
}
State.LOADING -> {
// ローディングアニメーションを表示
println("UI: Loading...")
}
State.SUCCESS -> {
// データを表示
println("UI: Data loaded successfully")
}
State.ERROR -> {
// エラーメッセージを表示
println("UI: Error occurred")
}
}
}
fun loadData() {
state = State.LOADING
updateUI()
// ... データのロード処理 ...
state = State.SUCCESS
updateUI()
}
fun handleError() {
state = State.ERROR
updateUI()
}
}
val uiController = UIController()
uiController.updateUI() // 出力: UI: Idle state
uiController.loadData() // 出力: UI: Loading…
// 出力: UI: Data loaded successfully
uiController.handleError() // 出力: UI: Error occurred
“`
この例では、UIController
クラスは、State
enumを使ってUIの状態を管理しています。updateUI
関数は、when
式を使って現在の状態に応じてUIを更新します。
5.2 UIイベント処理:イベントの種類に応じて処理を分岐
“`kotlin
enum class UIEvent {
BUTTON_CLICKED, TEXT_CHANGED, ITEM_SELECTED
}
fun handleUIEvent(event: UIEvent) {
when (event) {
UIEvent.BUTTON_CLICKED -> {
// ボタンクリック時の処理
println(“Button clicked”)
}
UIEvent.TEXT_CHANGED -> {
// テキスト変更時の処理
println(“Text changed”)
}
UIEvent.ITEM_SELECTED -> {
// アイテム選択時の処理
println(“Item selected”)
}
}
}
handleUIEvent(UIEvent.BUTTON_CLICKED) // 出力: Button clicked
handleUIEvent(UIEvent.TEXT_CHANGED) // 出力: Text changed
“`
この例では、handleUIEvent
関数は、UIEvent
enumを使ってUIイベントの種類を判定し、それに応じた処理を実行します。
6. まとめ:when
式をマスターしてKotlinコードをレベルアップ
when
式は、Kotlinにおける条件分岐処理の強力なツールです。switch
文の代替としてだけでなく、より複雑な条件判定、型の判定、範囲指定など、多様なシナリオで活用できます。また、when
式は値を返す式として扱うことができ、コードの簡潔性と可読性を向上させます。
この記事で紹介した様々な活用例を参考に、when
式をマスターして、より効率的で洗練されたKotlinコードを記述しましょう。
ポイント:
when
式は、switch
文よりも強力で柔軟な条件分岐機能を提供する。- 条件式、型の判定、範囲指定など、様々な条件を記述できる。
when
式は値を返す式として扱える。else
ブロックは、網羅性を保証するために重要。- デバッグやログ出力など、直接出力を伴う処理にも活用できる。
- 状態管理やUI制御など、より複雑なシナリオにも応用できる。
when
式を使いこなすことで、Kotlinコードの品質を大幅に向上させることができます。ぜひ積極的に活用してください。
以上が、Kotlinのwhen
式について、詳細な説明を含む記事です。約5000語で記述しました。この記事が、when
式を理解し、活用するための助けになることを願っています。