Kotlinのenum classについて

採用はこちら

Kotlinの enum class(列挙型クラス)は、取り得る値が限定される概念を型として安全に表現するための仕組みです。

単なる定数定義ではなく、「値+振る舞い+メタ情報」をまとめて扱える点が、Kotlinにおけるenumの本質です。

以下では、基本構文から実務設計での使いどころまでを正確性を重視して解説します。

目次

enum classの基本構文

enum class Color {
    RED,
    GREEN,
    BLUE
}

enumに定義された REDGREEN は、単なる値ではなく Color 型のインスタンスです。

それぞれはアプリケーション内に1つだけ存在します。

利用例

val color = Color.RED

when (color) {
    Color.RED -> println("赤")
    Color.GREEN -> println("緑")
    Color.BLUE -> println("青")
}
  • 比較は == で安全
  • null非許容で扱えるため、状態管理に向いている

enum classにプロパティを持たせる

enumはコンストラクタを持てます。

これにより、定数と付随情報を1か所に集約できます。

enum class Status(val code: Int, val label: String) {
    SUCCESS(200, "成功"),
    ERROR(500, "エラー"),
    LOADING(102, "処理中")
}
val status = Status.SUCCESS
println(status.code)   // 200
println(status.label)  // 成功

この形は以下の用途で特に有効です。

  • APIレスポンスのステータス管理
  • 画面状態(表示名+内部コード)
  • DBや通信で使う識別子の集中管理

enum classに関数を定義する

enum全体に共通するロジックも定義できます。

enum class Direction {
    NORTH, SOUTH, EAST, WEST;

    fun isVertical(): Boolean {
        return this == NORTH || this == SOUTH
    }
}
Direction.NORTH.isVertical() // true
Direction.EAST.isVertical()  // false

ロジックを外部に散らさず、型の責務としてまとめられる点がメリットです。

enum定数ごとに振る舞いを変える

Kotlinのenumは、定数ごとに処理を実装できます。

enum class Calculator {
    ADD {
        override fun apply(a: Int, b: Int) = a + b
    },
    SUB {
        override fun apply(a: Int, b: Int) = a - b
    };

    abstract fun apply(a: Int, b: Int): Int
}
Calculator.ADD.apply(3, 5) // 8
Calculator.SUB.apply(3, 5) // -2

この書き方の利点

  • when による分岐が不要
  • 処理の追加・変更がenum内で完結
  • Strategyパターンを自然に表現できる

実務では「状態ごとに処理が違う」場面で非常に有効です。

enumとwhenの網羅性チェック

enumを when 式で扱うと、すべてのenum定数を列挙しない限りコンパイルエラーになります。

fun message(status: Status): String =
    when (status) {
        Status.SUCCESS -> "OK"
        Status.ERROR -> "NG"
        Status.LOADING -> "WAIT"
    }
  • else が不要
  • enumに値を追加した際、分岐漏れをコンパイル時に検出可能

これはKotlinのenum設計における大きな強みです。

enumの全要素取得:values() と entries

values()

Status.values() // Array<Status>
  • 以前から使われているAPI
  • 配列を返すため、呼び出しごとにコピーが発生

entries(Kotlin 1.9+ 推奨)

Status.entries // EnumEntries<Status>
  • Kotlin 1.9 以降で安定版
  • 不変コレクション相当
  • パフォーマンス・設計面でこちらが推奨

values() は現在も使用可能ですが、新規コードでは entries を使うのが推奨されます。

valueOf() と安全な変換

val status = Status.valueOf("SUCCESS")
  • 存在しない名前の場合、IllegalArgumentException が発生

安全に扱う例

fun statusOf(name: String): Status? =
    Status.entries.find { it.name == name }

外部入力(API・フォーム・DB)を扱う場合は、このように nullable で受ける設計が安全です。

name / ordinal の注意点

Status.SUCCESS.name    // "SUCCESS"
Status.SUCCESS.ordinal // 0

注意点

  • ordinal定義順に依存
  • 並び替え・追加で値が変わる

❌ 永続化・通信での使用は避ける
✅ 明示的な codeid をプロパティとして持たせる

enum class Status(val code: Int) {
    SUCCESS(200),
    ERROR(500)
}

enum classとsealed classの使い分け

観点enum classsealed class
値の集合固定柔軟
状態の構造共通状態ごとに異なる
用途定数・状態表現力の高い状態

目安

  • 単純な状態・区分 → enum
  • 状態ごとに持つデータや構造が違う → sealed class

シリアライズとの関係

kotlinx.serialization を利用する場合、enumに @Serializable を付けて扱うのが一般的です。

@Serializable
enum class Role {
    ADMIN,
    USER,
    GUEST
}
  • JSONとの相性が良い
  • @SerialName を使えば外部表現の制御も可能

※ プロジェクト設定や使用ライブラリによって挙動は異なるため、「必須」ではなく「一般的な使い方」と理解すると安全です。

まとめ

  • enum classは「定数の集合」ではなく 振る舞いを持つ型
  • when と組み合わせることで 安全で変更に強い設計が可能
  • ordinal は使用しない
  • Kotlin 1.9+ では entries を優先
  • 分岐が増えたら「enum定数ごとの実装」を検討

以上、Kotlinのenum classについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次