Menu
Coddy logo textTech

データを持つ Enum

CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 14/61。

Rustの基本的なenumでは、Direction::NorthStatus::Activeのように、バリアントの集合が固定された型を定義できます。しかし、Rustのenumはそれよりはるかに強力です。各バリアントは独自のデータを持つことができるため、enumは現実世界のシナリオをモデル化するうえで非常に柔軟です。

異なるメッセージ型がそれぞれ異なる情報を持つメッセージングシステムを考えてみましょう。テキストメッセージには内容があり、移動コマンドには座標があり、終了シグナルには何もありません。Rustでは、これらすべてを単一のenumで表現できます。

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

Each バリアントは異なる形を持ちます。Quit はデータを holds しません。単なるシグナルです。

Moveはnamedフィールドを持つ構造体風の構文を使用します。Writeはタプル構文を使用して単一のStringを保持します。ChangeColorはRGBコンポーネントを表す3つの値を保持します。

これらのバリアントのインスタンスの作成は、次のようになります。

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);

このアプローチの優れた点は、m1m2m3m4がすべて同じ型、つまりMessageであることです。同じコレクションに格納したり、同じ関数に渡したり、1つの関数から任意のバリアントを返したりできます。enumは、各バリアントに必要な固有の情報を保持しながら、異なるデータ形状を1つの型の下に統合します。

challenge icon

チャレンジ

簡単

data を含む enum を使用して、さまざまな種類の alert を表す notification システムを構築しましょう。それぞれの notification type は異なる情報を持ちます。message を持つもの、数値を持つもの、単純な signal であるものがあります。

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

  • notification.rs: 3つの variant を持つ public な Notification enum を Define します。
    • Alert: 1つの String message を保持します(tuple syntax)
    • Reminder: named fields を保持します:title(String)と minutes(u32)
    • Dismiss: data を持たず、単なる signal です
  • main.rs: notification module を取り込み、各 variant の instance を1つずつ作成します。次に、3つの variant が同じ type でありながら異なる data を持てることを示すため、それぞれの notification に関する情報を Print します。

Print する際は、各 notification を表示するために debug formatting({:?})を使用します。この方法で Print できるように、enum に Debug trait を derive する必要があります。

出力には、3つすべての notification がそれぞれ1行ずつ表示されます。

Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismiss

たとえば、alert message が "Server down"、reminder の title が "Meeting"、minutes が 30 の場合、出力は次のようになります。

Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismiss

入力として、alert message、reminder title、reminder minutes の3つを受け取ります。

REQUIRED OUTPUT FORMAT: [Your translated content here]

自分で試してみよう

mod notification;

use notification::Notification;

fn main() {
    // 入力を読み取る
    let mut alert_message = String::new();
    std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
    let alert_message = alert_message.trim().to_string();

    let mut reminder_title = String::new();
    std::io::stdin().read_line(&mut reminder_title).expect("Failed to read line");
    let reminder_title = reminder_title.trim().to_string();

    let mut minutes_input = String::new();
    std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
    let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");

    // TODO: alert_message を使用して Alert 通知を作成する

    // TODO: Create a Reminder notification using reminder_title and reminder_minutes

    // TODO: Dismiss 通知を作成する

    // TODO: デバッグフォーマット {:?} を使用して各通知を出力する
    // 各通知はそれぞれ独自の行に出力すること
}
quiz icon腕試し

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

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

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