導入
「信号は 赤・黄・青 のどれか」「メッセージは 終了・移動・書き込み のどれか」——とりうる状態が決まっているものを表すのが enum(列挙型) です。Rust の enum は単なる定数の集まりではなく、各種類がデータを持てるのが強力な点です。
説明
enum Direction {
North,
South,
East,
West,
}
// 各種類がデータを持てる(ここが Rust の enum の真骨頂)
enum Message {
Quit, // データなし
Move { x: i32, y: i32 }, // 構造体のようなデータ
Write(String), // 文字列を1つ持つ
ChangeColor(i32, i32, i32), // タプルのようなデータ
}
fn main() {
let dir = Direction::East;
let msg = Message::Write(String::from("hello"));
// enum は match で分岐するのが定番
match msg {
Message::Quit => println!("終了"),
Message::Move { x, y } => println!("移動 ({x}, {y})"),
Message::Write(text) => println!("書き込み: {text}"),
Message::ChangeColor(r, g, b) => println!("色 ({r},{g},{b})"),
}
}
enum Direction { North, ... }… 4つのうちどれか1つ、という型。値はDirection::Northのように書きます。Messageの各種類は、それぞれ違う形のデータを持てます。Quit(なし)、Move(名前付きフィールド)、Write(文字列1つ)、ChangeColor(数値3つ)。1つの型で多様なケースを表現できます。- enum は
matchで分岐し、同時に中のデータを取り出せます(Message::Write(text)のtextに文字列が束縛される)。
第2章で学んだ match の網羅性チェックが、enum で本領を発揮します。Message に新しい種類を追加すると、その種類を処理していない match がすべてコンパイルエラーになり、対応漏れを教えてくれます。「状態を増やしたのに処理を書き忘れる」バグを、コンパイラが潰してくれるのです。
試すには
上の match から1つの腕(たとえば Message::Quit =>)を消すと、「パターンが網羅されていない」とエラーになります。enum と match の組み合わせは、Rust で「ありうる状態を漏れなく扱う」ための中心的な道具です。