Kotlinのwhen文で複数の値にマッチさせる方法を徹底解説

Kotlinのプログラミングにおいて、条件分岐を行う際に頻繁に使われるのがwhen文です。when文は、Javaのswitch文に似ていますが、より柔軟で強力な機能を持っています。特に、複数の値に対して条件を一括でマッチさせることができる点が特徴です。

例えば、複数の値を一つの条件としてまとめて処理することで、コードをシンプルに記述できます。本記事では、Kotlinのwhen文で複数の値にマッチさせる方法について、基本から応用まで分かりやすく解説します。

この記事を読むことで、when文の効果的な活用法を理解し、Kotlinでのプログラミングがさらに効率的になるでしょう。

目次

when文の基本構文

Kotlinのwhen文は、Javaのswitch文に似た条件分岐を行う構文です。しかし、when文はより直感的で柔軟な書き方ができ、さまざまな型や条件に対応しています。

基本的な構文

以下がwhen文の基本的な構文です。

val value = 3

when (value) {
    1 -> println("値は1です")
    2 -> println("値は2です")
    3 -> println("値は3です")
    else -> println("その他の値です")
}

各要素の説明

  • when (value):判定する対象の値を指定します。
  • 各条件 (1 ->, 2 ->, など)valueが特定の値にマッチしたときに実行する処理を指定します。
  • else:どの条件にもマッチしなかった場合に実行されるデフォルトの処理です。elseは省略可能ですが、指定しておくと安全です。

任意の式や値を指定可能

when文は、定数値だけでなく、任意の式や条件でも使用できます。

val num = 10

when {
    num < 0 -> println("負の数です")
    num == 0 -> println("ゼロです")
    num > 0 -> println("正の数です")
}

このように、when文はさまざまなシチュエーションに対応できる柔軟な構文です。次のセクションでは、複数の値にマッチさせる方法について解説します。

複数の値にマッチさせる方法

Kotlinのwhen文では、複数の値に対して一度にマッチさせることができます。カンマ , を使うことで、複数の条件を一括で指定でき、コードをシンプルに保つことが可能です。

複数の値を指定する基本構文

以下は、when文で複数の値にマッチさせる例です。

val day = "Monday"

when (day) {
    "Monday", "Tuesday", "Wednesday" -> println("平日です")
    "Saturday", "Sunday" -> println("週末です")
    else -> println("無効な日です")
}

解説

  • “Monday”, “Tuesday”, “Wednesday”:これらのいずれかの値にマッチした場合、「平日です」と出力します。
  • “Saturday”, “Sunday”:これらのいずれかにマッチした場合、「週末です」と出力します。
  • elseブロック:どの条件にもマッチしない場合に実行されます。

数値のマッチング

数値でも同様に複数の条件を指定できます。

val score = 85

when (score) {
    90, 95, 100 -> println("優秀です")
    70, 75, 80, 85 -> println("合格です")
    else -> println("再試験です")
}

この例のポイント

  • 90, 95, 100:スコアがこれらの値であれば「優秀です」と表示します。
  • 70, 75, 80, 85:これらのスコアにマッチしたら「合格です」と表示します。

文字列と数値の複合マッチ

文字列や数値、任意のデータ型を組み合わせた条件指定も可能です。

val input = "42"

when (input) {
    "yes", "ok", "sure" -> println("承認されました")
    "no", "cancel", "stop" -> println("拒否されました")
    "42", "100" -> println("特別な数値です")
    else -> println("不明な入力です")
}

まとめ

カンマ , を使うことで、複数の値に対する条件を効率的に記述できます。これにより、when文を使った条件分岐がシンプルかつ読みやすくなります。次のセクションでは、when文での範囲指定とパターンマッチについて解説します。

when文での範囲指定とパターンマッチ

Kotlinのwhen文は、複数の値だけでなく、範囲やパターンマッチによる条件分岐もサポートしています。これにより、より柔軟で効率的なコードを書くことができます。

範囲指定の基本

Kotlinでは、inキーワードを使って範囲内の値をマッチさせることができます。範囲指定には、数値や文字などを使用できます。

数値の範囲指定の例

val score = 75

when (score) {
    in 90..100 -> println("優秀です")
    in 70..89 -> println("合格です")
    in 0..69 -> println("不合格です")
    else -> println("無効なスコアです")
}

解説

  • in 90..100scoreが90から100の間にある場合にマッチします。
  • in 70..89scoreが70から89の間にある場合にマッチします。
  • else:範囲外の値に対するデフォルト処理です。

文字の範囲指定

文字の範囲指定も可能です。アルファベットの順序に基づいてマッチングを行います。

val grade = 'B'

when (grade) {
    in 'A'..'C' -> println("良い成績です")
    in 'D'..'F' -> println("普通の成績です")
    else -> println("無効な成績です")
}

パターンマッチの活用

when文では、複数の条件や型に応じたパターンマッチを行うことができます。

型に基づくマッチ

fun checkType(obj: Any) {
    when (obj) {
        is String -> println("文字列です")
        is Int -> println("整数です")
        is Boolean -> println("真偽値です")
        else -> println("不明な型です")
    }
}

checkType(42)       // 整数です
checkType("Hello")  // 文字列です
checkType(true)     // 真偽値です

複数条件の組み合わせ

範囲指定と複数の値を組み合わせることも可能です。

val input = 50

when (input) {
    in 1..10, in 40..50 -> println("範囲内の値です")
    else -> println("範囲外の値です")
}

まとめ

Kotlinのwhen文では、範囲指定やパターンマッチを活用することで、柔軟で読みやすい条件分岐が実現できます。次のセクションでは、elseの使い方について解説します。

when文でのelseの使い方

Kotlinのwhen文において、elseはどの条件にもマッチしない場合のデフォルト処理として使用されます。elseを適切に使うことで、予期しない入力や例外的なケースにも対応でき、プログラムの安全性を高めることができます。

基本的なelseの使い方

elseは、最後の条件ブロックとして記述されます。以下は基本的な使用例です。

val fruit = "Pineapple"

when (fruit) {
    "Apple" -> println("リンゴです")
    "Banana" -> println("バナナです")
    "Orange" -> println("オレンジです")
    else -> println("不明なフルーツです")
}

出力結果

不明なフルーツです

解説

  • elseブロックは、AppleBananaOrangeに該当しないすべての入力に対して適用されます。

elseを使用する理由

  1. 安全性の確保elseを指定することで、予期しない値が入力された場合でも適切に処理できます。
  2. デフォルト処理の明示:特定の条件にマッチしないケースを明示的に処理できます。
  3. エラー回避:全ての条件を網羅しなくてもエラーが発生しにくくなります。

elseを使った例外処理

when文をエラーハンドリングに使う場合、elseで例外的なケースを処理することが可能です。

fun validateInput(input: Int) {
    when (input) {
        in 1..10 -> println("1から10の範囲内です")
        in 11..20 -> println("11から20の範囲内です")
        else -> println("無効な入力です")
    }
}

validateInput(25)  // 無効な入力です

elseを省略する場合

when文で条件が完全に網羅されている場合、elseを省略できます。例えば、Boolean型の場合:

val condition = true

when (condition) {
    true -> println("真です")
    false -> println("偽です")
}

この場合、truefalseの2つしか可能性がないため、elseは不要です。

まとめ

  • elseはどの条件にもマッチしない場合のデフォルト処理です。
  • 予期しない入力や例外的なケースを処理するために役立ちます。
  • 全てのケースを網羅する場合はelseを省略できます。

次のセクションでは、when文を用いた具体的なコード例について解説します。

実際のコード例

ここでは、Kotlinのwhen文で複数の値や範囲、パターンマッチを組み合わせた具体的なコード例を紹介します。これにより、when文の柔軟な使い方を理解しましょう。

複数の値にマッチする例

複数の条件をカンマ , で区切って指定する基本的な例です。

val weather = "Cloudy"

when (weather) {
    "Sunny", "Clear" -> println("天気は晴れです")
    "Rainy", "Stormy" -> println("天気は雨です")
    "Cloudy", "Overcast" -> println("天気は曇りです")
    else -> println("不明な天気です")
}

出力結果

天気は曇りです

範囲指定の例

数値に対して範囲を用いたマッチングの例です。

val age = 25

when (age) {
    in 0..12 -> println("子供です")
    in 13..19 -> println("ティーンエイジャーです")
    in 20..64 -> println("大人です")
    in 65..100 -> println("高齢者です")
    else -> println("無効な年齢です")
}

出力結果

大人です

型に基づくマッチングの例

オブジェクトの型に応じた条件分岐の例です。

fun describe(obj: Any) {
    when (obj) {
        is String -> println("これは文字列です:$obj")
        is Int -> println("これは整数です:$obj")
        is Boolean -> println("これは真偽値です:$obj")
        else -> println("不明な型です")
    }
}

describe("Kotlin")   // これは文字列です:Kotlin
describe(42)         // これは整数です:42
describe(true)       // これは真偽値です:true

条件式を使ったマッチングの例

条件式を直接書いて複雑なマッチングを行う例です。

val number = 15

when {
    number % 2 == 0 -> println("偶数です")
    number % 3 == 0 -> println("3で割り切れます")
    number > 10 -> println("10より大きいです")
    else -> println("その他の数です")
}

出力結果

3で割り切れます

複数の条件や範囲を組み合わせた例

複数のマッチング方法を組み合わせた例です。

val score = 85

when (score) {
    in 90..100 -> println("素晴らしい成績です")
    in 70..89, 60 -> println("合格です")
    else -> println("不合格です")
}

出力結果

合格です

まとめ

これらの具体例を通して、when文が非常に柔軟であることが理解できたと思います。複数の値、範囲指定、型チェック、条件式などを適切に組み合わせることで、効率的で読みやすいコードを実現できます。

次のセクションでは、when文を使ったエラーハンドリングについて解説します。

when文を使ったエラーハンドリング

Kotlinのwhen文は、エラーハンドリングにも非常に有用です。特定の例外やエラーコードに基づいて処理を分岐することで、コードの可読性と保守性を向上させることができます。ここでは、when文を活用したエラーハンドリングの具体的な方法を解説します。

エラーコードを基にした処理分岐

APIやシステムエラーで返されるエラーコードに基づいて処理を分岐する例です。

fun handleError(code: Int) {
    when (code) {
        400, 401, 403 -> println("クライアントエラーです")
        404 -> println("リソースが見つかりません")
        in 500..599 -> println("サーバーエラーです")
        else -> println("不明なエラーです")
    }
}

handleError(404)  // リソースが見つかりません
handleError(500)  // サーバーエラーです

解説

  • 400, 401, 403:クライアントエラーに該当する場合の処理。
  • 404:特定のリソースが見つからないエラー。
  • in 500..599:サーバーエラーの範囲をカバー。
  • else:予期しないエラーコードに対するデフォルト処理。

例外クラスを基にした処理分岐

例外処理においてwhen文を使い、異なる種類の例外に応じた処理を行う方法です。

fun processFile(fileName: String) {
    try {
        val fileContent = readFile(fileName)
        println(fileContent)
    } catch (e: Exception) {
        when (e) {
            is FileNotFoundException -> println("ファイルが見つかりません: $fileName")
            is IOException -> println("ファイル読み取り中にエラーが発生しました")
            else -> println("予期しないエラーが発生しました: ${e.message}")
        }
    }
}

fun readFile(fileName: String): String {
    throw FileNotFoundException()
}

processFile("test.txt")

出力結果

ファイルが見つかりません: test.txt

解説

  • FileNotFoundException:ファイルが見つからない場合のエラーメッセージ。
  • IOException:ファイル読み取り中に発生する一般的なI/Oエラー。
  • else:上記以外の例外に対する処理。

複数のエラーメッセージに対応する例

文字列のエラーメッセージを条件として処理を分岐する例です。

fun displayErrorMessage(error: String) {
    when (error) {
        "NETWORK_ERROR", "TIMEOUT" -> println("ネットワークに問題があります")
        "AUTH_ERROR" -> println("認証に失敗しました")
        "UNKNOWN_ERROR" -> println("不明なエラーが発生しました")
        else -> println("その他のエラー: $error")
    }
}

displayErrorMessage("TIMEOUT")  // ネットワークに問題があります

まとめ

Kotlinのwhen文をエラーハンドリングに活用することで、シンプルでわかりやすいエラー処理が可能になります。エラーコード、例外クラス、エラーメッセージなど、さまざまな要素に応じた柔軟な処理が行えるため、プログラムの信頼性が向上します。

次のセクションでは、when文で複数のデータ型に対応する方法について解説します。

複数のデータ型に対応する方法

Kotlinのwhen文は、異なるデータ型に対して柔軟に条件分岐することができます。is演算子を使って、対象のオブジェクトの型に応じた処理を記述することで、型安全かつ簡潔なコードを実現できます。

基本的な型チェック

is演算子を使うことで、オブジェクトの型をチェックし、その型に応じた処理を実行できます。

fun processInput(input: Any) {
    when (input) {
        is String -> println("入力は文字列です: $input")
        is Int -> println("入力は整数です: $input")
        is Boolean -> println("入力は真偽値です: $input")
        else -> println("入力は不明な型です")
    }
}

processInput("Hello")   // 入力は文字列です: Hello
processInput(42)        // 入力は整数です: 42
processInput(true)      // 入力は真偽値です: true
processInput(3.14)      // 入力は不明な型です

複数の型に同時にマッチさせる

複数の型に対して同じ処理を行いたい場合は、条件をまとめることができます。

fun checkType(input: Any) {
    when (input) {
        is Int, is Double, is Float -> println("入力は数値型です: $input")
        is String -> println("入力は文字列です: $input")
        else -> println("入力はその他の型です")
    }
}

checkType(100)        // 入力は数値型です: 100
checkType(3.14)       // 入力は数値型です: 3.14
checkType("Kotlin")   // 入力は文字列です: Kotlin

スマートキャストの活用

Kotlinでは、is演算子で型が判定された後、その型にキャストする「スマートキャスト」が自動的に行われます。これにより、明示的なキャストが不要になります。

fun printLength(input: Any) {
    when (input) {
        is String -> println("文字列の長さ: ${input.length}")
        is List<*> -> println("リストの要素数: ${input.size}")
        else -> println("長さを取得できない型です")
    }
}

printLength("Hello")         // 文字列の長さ: 5
printLength(listOf(1, 2, 3)) // リストの要素数: 3
printLength(123)             // 長さを取得できない型です

データクラスを用いた型チェック

複数のデータクラスを用いた型チェックもwhen文で簡単に実現できます。

data class Success(val message: String)
data class Error(val code: Int, val message: String)

fun handleResponse(response: Any) {
    when (response) {
        is Success -> println("成功: ${response.message}")
        is Error -> println("エラー [${response.code}]: ${response.message}")
        else -> println("未知のレスポンス")
    }
}

handleResponse(Success("データの取得に成功しました"))  
// 成功: データの取得に成功しました

handleResponse(Error(404, "ページが見つかりません"))    
// エラー [404]: ページが見つかりません

まとめ

  • is演算子を使うことで、オブジェクトの型に応じた処理を行えます。
  • 異なるデータ型に同じ処理を適用する場合、複数の型を条件に指定できます。
  • スマートキャストにより、型チェック後は安全にプロパティやメソッドを利用できます。

次のセクションでは、when文を使った応用例として、複雑な条件分岐について解説します。

応用例:複雑な条件分岐

Kotlinのwhen文は、シンプルな条件分岐だけでなく、複雑なロジックや高度な条件を実現するのにも適しています。複数の要素や条件式、カスタムロジックを組み合わせることで、可読性を保ちながら効率的なコードを書けます。

複数の条件式を使った分岐

when文では、条件式を直接記述し、論理演算子を組み合わせた複雑な判定が可能です。

fun evaluateNumber(num: Int) {
    when {
        num % 2 == 0 && num > 0 -> println("正の偶数です")
        num % 2 == 0 && num < 0 -> println("負の偶数です")
        num % 2 != 0 && num > 0 -> println("正の奇数です")
        num % 2 != 0 && num < 0 -> println("負の奇数です")
        num == 0 -> println("ゼロです")
    }
}

evaluateNumber(8)     // 正の偶数です
evaluateNumber(-3)    // 負の奇数です
evaluateNumber(0)     // ゼロです

条件の組み合わせによる入力検証

複数の条件を組み合わせて、ユーザー入力の検証を行う例です。

fun validateInput(input: String) {
    when {
        input.isBlank() -> println("入力が空白です")
        input.length < 5 -> println("入力が短すぎます")
        input.any { it.isDigit() } -> println("入力に数字が含まれています")
        else -> println("入力が正常です")
    }
}

validateInput("")            // 入力が空白です
validateInput("Hi")          // 入力が短すぎます
validateInput("Hello123")    // 入力に数字が含まれています
validateInput("Kotlin")      // 入力が正常です

データクラスと条件分岐の組み合わせ

複数の条件を考慮したデータ処理の例です。データクラスを使って、状態ごとに異なる処理を実行します。

data class Order(val status: String, val amount: Double)

fun processOrder(order: Order) {
    when (order) {
        Order("Paid", amount = in 0.0..100.0) -> println("少額の有料注文です")
        Order("Paid", amount = in 100.0..1000.0) -> println("高額の有料注文です")
        Order("Pending", amount = in 0.0..1000.0) -> println("未払いの注文です")
        Order("Cancelled", amount = in 0.0..1000.0) -> println("キャンセルされた注文です")
        else -> println("不明な注文です")
    }
}

processOrder(Order("Paid", 50.0))        // 少額の有料注文です
processOrder(Order("Pending", 200.0))    // 未払いの注文です
processOrder(Order("Cancelled", 500.0))  // キャンセルされた注文です

列挙型 (Enum) の活用

列挙型 (enum class) を使った条件分岐も、when文と相性が良いです。

enum class Status {
    SUCCESS, ERROR, LOADING
}

fun handleStatus(status: Status) {
    when (status) {
        Status.SUCCESS -> println("処理が成功しました")
        Status.ERROR -> println("エラーが発生しました")
        Status.LOADING -> println("処理中です")
    }
}

handleStatus(Status.SUCCESS)  // 処理が成功しました

複数の条件を考慮したデータのフィルタリング

複数の条件でデータをフィルタリングする例です。

val numbers = listOf(-5, 0, 3, 8, -2, 10)

val filteredNumbers = numbers.filter {
    when {
        it > 0 && it % 2 == 0 -> true  // 正の偶数のみを残す
        else -> false
    }
}

println(filteredNumbers)  // [8, 10]

まとめ

Kotlinのwhen文を使えば、複雑な条件分岐をシンプルかつ読みやすく記述できます。条件式、データクラス、列挙型を組み合わせることで、より高度なロジックを効率的に処理できます。

次のセクションでは、記事全体の内容をまとめます。

まとめ

本記事では、Kotlinのwhen文を使って複数の値にマッチさせる方法について詳しく解説しました。基本構文から始まり、複数の値や範囲指定、パターンマッチ、型ごとの条件分岐、さらには応用例として複雑な条件分岐やエラーハンドリングの実装方法まで網羅しました。

when文はJavaのswitch文と異なり、柔軟かつ直感的に記述できるため、シンプルな条件分岐から高度なロジックまで幅広く対応できます。特に、カンマ,で複数の値を指定したり、is演算子で型を判定することで、可読性と効率性が向上します。

Kotlinプログラムにおいてwhen文を適切に活用することで、コードの品質と保守性を向上させることができます。ぜひ、実際の開発でwhen文を積極的に使ってみてください。

コメント

コメントする

目次