複合データに列挙型バリアントを使用する
列挙型は、複数のバリアントのいずれも指定できる型です。 Rust で列挙型と呼ぶものは、より一般的には代数的データ型として知られています。 重要な詳細は、各列挙型バリアントには、それに付随するデータを指定できることです。
列挙型の作成には enum
キーワードを使用します。これには、列挙型バリアントを任意に組み合わせることができます。 列挙型バリアントは、構造体と同様に、名前があるフィールドを持つことが可能です。しかし、名前がないフィールドを持つことも、まったくフィールドを持たないことも可能です。 構造体型と同様に、列挙型も大文字になります。
列挙型の定義
次の例では、Web イベントを分類する列挙型を定義します。 列挙型内の各バリアントは独立しており、さまざまな量と型の値を格納します。
enum WebEvent {
// An enum variant can be like a unit struct without fields or data types
WELoad,
// An enum variant can be like a tuple struct with data types but no named fields
WEKeys(String, char),
// An enum variant can be like a classic struct with named fields and their data types
WEClick { x: i64, y: i64 }
}
この例の列挙型には、型が異なる 3 つのバリアントがあります。
WELoad
には、データ型またはデータが関連付けられていません。WEKeys
には、データ型がString
およびchar
である 2 つのフィールドがあります。WEMClick
には、名前付きフィールドx
とy
、およびそれらのデータ型 (i64
) を持つ匿名構造体が含まれています。
さまざまな種類の構造体型を定義するのと同様の方法で、バリアントのある列挙型を定義します。 すべてのバリアントは、同じ WebEvent
列挙型でグループ化されます。 列挙型の各バリアントは、独自の型ではありません。 WebEvent
列挙型のバリアントを使用する関数はすべて、列挙型内のすべてのバリアントを受け入れる必要があります。 WEClick
バリアントだけを受け入れ、他のバリアントは受け入れない関数を使用することはできません。
構造体を使用して列挙型を定義する
列挙型のバリアント要件を回避する方法は、列挙型のバリアントごとに個別の構造体を定義することです。 次に、列挙型の各バリアントでは、対応する構造体が使用されます。 構造体には、対応する列挙型バリアントによって保持されていたものと同じデータが保持されます。 この定義スタイルにより、それぞれの論理バリアントを単独で参照できるようになります。
次のコードは、この代替定義スタイルを使用する方法を示しています。 構造体は、データを保持するように定義されています。 列挙型のバリアントは、構造体を参照するように定義されています。
// Define a tuple struct
struct KeyPress(String, char);
// Define a classic struct
struct MouseClick { x: i64, y: i64 }
// Redefine the enum variants to use the data from the new structs
// Update the page Load variant to have the boolean type
enum WebEvent { WELoad(bool), WEClick(MouseClick), WEKeys(KeyPress) }
列挙型をインスタンス化する
次に、列挙型バリアントのインスタンスを作成するコードを追加しましょう。 バリアントごとに、let
キーワードを使用して代入を行います。 列挙型の定義で特定のバリアントにアクセスするには、二重コロン ::
を含む構文 <enum>::<variant>
を使用します。
単純なバリアント: WELoad(bool)
WebEvent
列挙型の最初のバリアントには、WELoad(bool)
という 1 つのブール値があります。 このバリアントは、前のユニットでブール値を操作した場合と同様の方法でインスタンス化します。
let we_load = WebEvent::WELoad(true);
構造体バリアント: WEClick(MouseClick)
2 番目のバリアントには、従来の構造体 WEClick(MouseClick)
が含まれています。 構造体には x
および y
という 2 つの名前付きフィールドがあり、両方のフィールドに i64
データ型があります。 このバリアントを作成するには、まず構造体をインスタンス化します。 次に、バリアントをインスタンス化するための呼び出しで、構造体を引数として渡します。
// Instantiate a MouseClick struct and bind the coordinate values
let click = MouseClick { x: 100, y: 250 };
// Set the WEClick variant to use the data in the click struct
let we_click = WebEvent::WEClick(click);
タプル バリアント: WEKeys(KeyPress)
最後のバリアントにはタプル WEKeys(KeyPress)
が含まれています。 タプルには、String
および char
データ型を使用する 2 つのフィールドがあります。 このバリアントを作成するには、まずタプルをインスタンス化します。 次に、バリアントをインスタンス化するための呼び出しで、タプルを引数として渡します。
// Instantiate a KeyPress tuple and bind the key values
let keys = KeyPress(String::from("Ctrl+"), 'N');
// Set the WEKeys variant to use the data in the keys tuple
let we_key = WebEvent::WEKeys(keys);
このコードでは、String::from("<value>")
構文を使用していることに注意してください。 この構文では、Rust の from
メソッドを呼び出すことによって型 String
の値が作成されます。 メソッドには、二重引用符で囲まれたデータの入力引数が必要です。
列挙型の例
列挙型バリアントをインスタンス化するための最終的なコードは次のようになります。
// Define a tuple struct
#[derive(Debug)]
struct KeyPress(String, char);
// Define a classic struct
#[derive(Debug)]
struct MouseClick { x: i64, y: i64 }
// Define the WebEvent enum variants to use the data from the structs
// and a boolean type for the page Load variant
#[derive(Debug)]
enum WebEvent { WELoad(bool), WEClick(MouseClick), WEKeys(KeyPress) }
fn main() {
// Instantiate a MouseClick struct and bind the coordinate values
let click = MouseClick { x: 100, y: 250 };
println!("Mouse click location: {}, {}", click.x, click.y);
// Instantiate a KeyPress tuple and bind the key values
let keys = KeyPress(String::from("Ctrl+"), 'N');
println!("\nKeys pressed: {}{}", keys.0, keys.1);
// Instantiate WebEvent enum variants
// Set the boolean page Load value to true
let we_load = WebEvent::WELoad(true);
// Set the WEClick variant to use the data in the click struct
let we_click = WebEvent::WEClick(click);
// Set the WEKeys variant to use the data in the keys tuple
let we_key = WebEvent::WEKeys(keys);
// Print the values in the WebEvent enum variants
// Use the {:#?} syntax to display the enum structure and data in a readable form
println!("\nWebEvent enum structure: \n\n {:#?} \n\n {:#?} \n\n {:#?}", we_load, we_click, we_key);
}
Rust Playground 内で、このコード例を操作してみてください。
デバッグ ステートメント
前の例で、次のコード ステートメントを探します。 このステートメントは、コード内のいくつかの場所で使用されています。
// Set the Debug flag so we can check the data in the output
#[derive(Debug)]
#[derive(Debug)]
構文を使用すると、コードの実行中に、標準出力では見ることのできない特定の値を確認できます。 println!
マクロでデバッグ データを表示するには、構文 {:#?}
を使用して、読み取り可能な方法でデータを書式設定します。
自分の知識をチェックする
次の質問に答えて、学習した内容を確認してください。 質問ごとに回答を 1 つ選択して、[回答を確認] を選択します。