SwiftのenumはC++のenum classよりsum typeとして見ると分かりやすい
Swiftの enum は、C++の enum class だけを想像すると少し足りません。
単なる名前付き整数というより、状態の種類と値をまとめて表せるsum typeとして見ると理解しやすいです。
公式でも、Swiftのenumerationはcaseを定義し、caseごとにassociated valueを持てるものとして説明されています。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations/
普通のenum
まずは単純なenumです。
enum Direction {
case up
case down
case left
case right
}
使う側はこうです。
let direction: Direction = .up
このあたりはC++の enum class に近いです。
enum class Direction {
up,
down,
left,
right,
};
associated values
Swiftらしいのはここからです。
enum LoadState {
case idle
case loading
case loaded([String])
case failed(Error)
}
loaded は配列を持ち、failed は Error を持ちます。
let state = LoadState.loaded(["A", "B"])
C++で近いことをするなら、std::variant に寄せる感覚です。
using LoadState = std::variant<Idle, Loading, Loaded, Failed>;
Swiftのenumは、caseと値の組み合わせを言語機能として扱えます。
switchで取り出す
associated valueは switch で取り出します。
switch state {
case .idle:
print("idle")
case .loading:
print("loading")
case .loaded(let items):
print(items)
case .failed(let error):
print(error)
}
Swiftの switch は網羅性チェックがあります。
caseを追加すると、対応していないswitchでコンパイルエラーになります。
このチェックはかなり助かります。状態が増えたときに、表示や処理を直し忘れにくいです。
Optionalもenumとして見られる
Swiftの Optional も、だいたいenumとして考えられます。
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
実際の定義は標準ライブラリ側ですが、考え方としてはこうです。
String? は「Stringがある」か「ない」かのenumだと思うと、C++の std::optional<T> にかなり近いです。
Optionalについては SwiftのOptionalをC++のnullptrやstd::optionalと比べて整理する に分けています。
まとめ
Swiftのenumは、C++の enum class より広いものとして見るとよいです。
- 単純なcase列挙もできる
- caseごとに値を持てる
switchで値を取り出せる- 網羅性チェックが効く
std::variantやstd::optionalに近い使い方もある
状態管理を書くときは、まずenumで表せないかを見ると、Swiftでは自然な形になりやすいです。


