Enum のメソッド
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 15/61。
構造体と同様に、列挙型にはimplブロックで定義されたメソッドを持たせることができます。これにより、動作を列挙型に直接関連付けることができ、統一されたインターフェースを通じて異なるvariantを簡単に扱えるようになります。
前のレッスンのMessage enumにメソッドを追加する方法は次のとおりです:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}
impl Message {
fn describe(&self) -> String {
match self {
Message::Quit => String::from("Quit signal"),
Message::Move { x, y } => format!("Move to ({}, {})", x, y),
Message::Write(text) => format!("Message: {}", text),
}
}
}
impl Message ブロックは、構造体の場合とまったく同じように機能します。このメソッドは、列挙型のインスタンスにアクセスするために &self を受け取ります。メソッド内では match を使って、どの variant を扱っているのかを判断し、appropriate な result を返します。
どの variant を持っているかにかかわらず、method の呼び出し方は同じです:
fn main() {
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
println!("{}", m1.describe()); // 終了シグナル
println!("{}", m2.describe()); // (10, 20) へ移動
}
このパターンが強力なのは、呼び出し元がどのvariantを持っているか知る必要がないからです。呼び出し元はmethodを呼び出すだけで、enumが内部ですべて処理します。variantに応じて動作は変わりますが、インターフェースは一貫したままです。
チャレンジ
簡単現在の信号の状態を説明する enum と method を使用する信号機システムを構築しましょう。各 light の色には持続時間の情報を持たせ、method によって人間が読みやすい説明を提供します。
コードを整理するために、2つのファイルを作成します。
traffic.rs:TrafficLightという public なenumを、three つの variant で Define します。Red: 待機する秒数を表すu32を保持しますYellow: 待機する秒数を表すu32を保持しますGreen: 進む秒数を表すu32を保持します
Stringを返すstatusmethod を Implement します。method 内でmatchを使用して each variant を handle し、duration を message に含めます。main.rs: traffic module を読み込み、each light variant の instances を Create し、それぞれに対してstatusmethod を Call して説明を print します。
status method は、次の exact な形式の messages を返す should あります。
Redの場合:Stop for {seconds} secondsYellowの場合:Caution for {seconds} secondsGreenの場合:Go for {seconds} seconds
output では、each light の status がそれぞれ独自の line に表示される should あります。
Stop for {seconds} seconds
Caution for {seconds} seconds
Go for {seconds} secondsたとえば、red light が 30 seconds、yellow が 5 seconds、green が 25 seconds の場合、output は次のようになります。
Stop for 30 seconds
Caution for 5 seconds
Go for 25 secondsthree つの入力を受け取ります。red light の duration、yellow light の duration、green light の duration です。
自分で試してみよう
mod traffic;
use traffic::TrafficLight;
fn main() {
// 継続時間の入力を読み取る
let mut red_input = String::new();
std::io::stdin().read_line(&mut red_input).expect("Failed to read line");
let red_duration: u32 = red_input.trim().parse().expect("Invalid number");
let mut yellow_input = String::new();
std::io::stdin().read_line(&mut yellow_input).expect("Failed to read line");
let yellow_duration: u32 = yellow_input.trim().parse().expect("Invalid number");
let mut green_input = String::new();
std::io::stdin().read_line(&mut green_input).expect("Failed to read line");
let green_duration: u32 = green_input.trim().parse().expect("Invalid number");
// TODO: 入力された継続時間で各TrafficLightバリアントのインスタンスを作成する
// TODO: 各ライトでstatusメソッドを呼び出し、結果を出力する
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ