100日後にRustをちょっと知ってる人になる: [Day 45]列挙型
Day 45 のテーマ
Day 44 では様々なデータ型の要素を集めるための仕組みの構造体について見てみました。
データをまとめる仕組みとして、Rust には列挙型というものもあります。Java をはじめとして、その他の言語にもありますよね。様々な値を文字通り列挙しておき、そのうちのどれか 1 つの値のみを取り出すようなデータ型です。この、Rust での列挙型の使い方について今日は見てみたいと思います。
列挙型
Java あるいは C/C++ などの経験がある人は、列挙型というよりも enum と呼んだ方が分かりやすいのかもしれません。
列挙型とは、様々なとりうる値を予め列挙しておき、必要に応じて列挙されている中からどれか 1 つの値のみを取り出して使用するというようなデータ型です。
ここで、列挙した値のことを列挙子 (variant) と呼びます。
構造体と列挙型の違いは、既に分かってもらえたかもしれないですが、次のような考えかたの違いになります:
- 構造体: 各要素 (フィールド)を全て対象にして扱う
- 列挙型: 各要素のいずれか 1 つとして扱う
複数のデータを収めるということは同じような考え方だとしても、含まれているデータの取り扱いに関して考え方が違うことが分かります。
列挙型の定義の仕方
列挙型は enum
キーワードを使用して定義を行います。
以下のように enum
キーワード に続けて、この列挙型の名前を定義し、列挙子を並べて定義を行います。
enum ANIMAL {
DOG,
CAT,
RABBIT,
MOUSE,
}
この列挙型から列挙子を参照する場合は、::
を用いて指定を行います。
let your_pet = ANIMAL::CAT;
let my_pet = ANIMAL::DOG;
列挙子へのデータ格納
Rust では 列挙子に対してデータを持たせて列挙型を構成することが可能です。
enum Shape {
Line {x1: i32, y1: i32, x2: i32, y2: i32},
Circle {x: i32, y: i32, r: i32},
}
上記の例を見ると分かるように、Shape
列挙型に対して、Line
構造体と Circle
構造体をそれぞれ列挙子として並べています。
また次のように、タプル構造体として列挙子を追加することも可能です。
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
V4
は、IP アドレスを表すタプル構造体になっています。
V6
は、文字列を値とするタプル構造体になっています。
このような列挙型からとりだす値の初期化は、それぞれ構造体なら構造体、タプル構造体ならタプル構造体の方式で行います。
// 構造体の初期化
let line = Shape::Line {x1: 100, y1: 100, x2: 400, y2: 400};
// タプル構造体の初期化
let myhome = IpAddr::V4(127, 0, 0, 1);
Day 45 のまとめ
Java で列挙型に慣れ親しんだことがある人は、少し違いを感じるかもしれません。
とは言え、そこまで大きな違いではなく分かってしまえばシンプルなデータ型ですよね。
構造体と列挙型、これらのデータ型をうまく使うことにより、必要に応じてオブジェクト指向のようなデザインが出来るのではないでしょうか。
Discussion