Menu
Coddy logo textTech

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に応じて動作は変わりますが、インターフェースは一貫したままです。

challenge icon

チャレンジ

簡単

現在の信号の状態を説明する enummethod を使用する信号機システムを構築しましょう。各 light の色には持続時間の情報を持たせ、method によって人間が読みやすい説明を提供します。

コードを整理するために、2つのファイルを作成します。

  • traffic.rs: TrafficLight という public な enum を、three つの variant で Define します。
    • Red: 待機する秒数を表す u32 を保持します
    • Yellow: 待機する秒数を表す u32 を保持します
    • Green: 進む秒数を表す u32 を保持します
    次に、span>light を説明する String を返す status method を Implement します。method 内で match を使用して each variant を handle し、duration を message に含めます。
  • main.rs: traffic module を読み込み、each light variant の instances を Create し、それぞれに対して status method を Call して説明を print します。

status method は、次の exact な形式の messages を返す should あります。

  • Red の場合: Stop for {seconds} seconds
  • Yellow の場合: Caution for {seconds} seconds
  • Green の場合: 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 seconds

three つの入力を受け取ります。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メソッドを呼び出し、結果を出力する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rustオンラインコンパイラ