Kotlinの enum class(列挙型クラス)は、取り得る値が限定される概念を型として安全に表現するための仕組みです。
単なる定数定義ではなく、「値+振る舞い+メタ情報」をまとめて扱える点が、Kotlinにおけるenumの本質です。
以下では、基本構文から実務設計での使いどころまでを正確性を重視して解説します。
enum classの基本構文
enum class Color {
RED,
GREEN,
BLUE
}
enumに定義された RED や GREEN は、単なる値ではなく 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は 定義順に依存- 並び替え・追加で値が変わる
❌ 永続化・通信での使用は避ける
✅ 明示的な code や id をプロパティとして持たせる
enum class Status(val code: Int) {
SUCCESS(200),
ERROR(500)
}
enum classとsealed classの使い分け
| 観点 | enum class | sealed 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についてでした。
最後までお読みいただき、ありがとうございました。










