0Pricing
Learn Rust Coding · 课时

带数据的枚举

为变体附加值。

带数据的枚举 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

变体可以携带数据

到目前为止,我们的变体都只是名称。在 Rust 中,变体还可以在圆括号中携带数据。

这样,单个枚举就可以同时描述值的种类和值本身。

enum Message {
    Quit,
    Move(i32, i32),
    Write(String),
}

携带一个值的变体

在圆括号中写入一个类型,即可为变体附加一项数据。

这里的 Celsius(f64) 表示 Celsius 变体携带一个 f64 数字。创建该值时,需要提供这个数字。

enum Temperature {
    Celsius(f64),
    Fahrenheit(f64),
}

fn main() {
    let t = Temperature::Celsius(21.5);
    println!("Created a temperature");
}

携带多个值的变体

一个变体可以携带多个值,各值之间用逗号分隔。

Move(i32, i32) 存储两个整数,例如 x 坐标和 y 坐标。创建它时需要同时传入这两个值。

enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
}

fn main() {
    let r = Shape::Rectangle(3.0, 4.0);
    println!("Made a rectangle");
}

使用 match 提取数据

要读取变体中的数据,请在模式中命名它。这个名称会成为您可以在该分支中使用的变量。

这里的 Shape::Circle(r) 会将存储的半径绑定到 r。

enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
}

fn main() {
    let s = Shape::Circle(2.0);
    match s {
        Shape::Circle(r) => println!("radius {}", r),
        Shape::Rectangle(w, h) => println!("{} x {}", w, h),
    }
}

使用绑定的值

数据绑定到名称后,您就可以像使用任何变量一样用它进行计算。

该程序会匹配一个形状并计算其面积,然后从 match 返回结果。

enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
}

fn main() {
    let s = Shape::Rectangle(3.0, 4.0);
    let area = match s {
        Shape::Circle(r) => 3.14 * r * r,
        Shape::Rectangle(w, h) => w * h,
    };
    println!("area = {}", area);
}

每个变体可以携带不同的数据

每个变体都可以携带不同形式的数据,也可以完全不携带数据。

正是这种灵活性让枚举具有很强的表达能力:一种类型可以表示许多不同的情况。

enum Message {
    Quit,
    Move(i32, i32),
    Write(String),
}

类似结构体的变体

变体可以像结构体一样使用带有花括号的命名字段。这样可以清楚地表达每个字段的含义。

构造它时需要为每个字段命名,匹配时也要使用相同的方式。

enum Event {
    Click { x: i32, y: i32 },
    KeyPress(char),
}

fn main() {
    let e = Event::Click { x: 10, y: 20 };
    match e {
        Event::Click { x, y } => println!("click at {},{}", x, y),
        Event::KeyPress(c) => println!("key {}", c),
    }
}

变体中的字符串

变体可以保存 String 这样的所有权数据。通过匹配,您可以访问其中的文本。

注意:按值匹配会将数据移出,不过这里可以这样做,因为我们会立即使用它。

enum Message {
    Write(String),
    Quit,
}

fn main() {
    let m = Message::Write(String::from("hello"));
    match m {
        Message::Write(text) => println!("text: {}", text),
        Message::Quit => println!("bye"),
    }
}

标准 Option 枚举

Rust 内置的 Option<T> 是一个带数据的枚举:Some(T) 保存一个值,而 None 什么也不保存。

Rust 使用它来表示“可能有一个值”,而不使用 null。匹配它的方式与匹配您自己的枚举相同。

fn main() {
    let maybe: Option<i32> = Some(5);
    match maybe {
        Some(n) => println!("got {}", n),
        None => println!("nothing"),
    }
}

综合运用

这个完整的程序会对温度进行建模,然后在 match 中将摄氏温度读数转换为华氏温度。

请尝试更改变体或它的值,然后重新运行。

enum Temperature {
    Celsius(f64),
    Fahrenheit(f64),
}

fn main() {
    let t = Temperature::Celsius(25.0);
    let f = match t {
        Temperature::Celsius(c) => c * 9.0 / 5.0 + 32.0,
        Temperature::Fahrenheit(f) => f,
    };
    println!("{} F", f);
}

何时使用带数据的变体

当每种情况自然地带有额外信息时,请使用携带数据的变体。

  • Circle 需要一个半径。
  • Write 消息需要它的文本。
  • Move 需要坐标。

将数据与变体捆绑在一起,可以让相关信息保持在一起,并确保类型安全。

快速检查

检查您对携带数据的枚举的理解。

回顾

您已经学会了枚举变体可以携带数据:一个值、多个值、类似结构体的命名字段,或者完全不携带数据。

您还学会了在 match 模式中为数据命名来读取它,例如 Circle(r)。标准的 Option 类型使用相同的方式。接下来,您将使用守卫和绑定来进一步细化匹配。

常见问题解答

「带数据的枚举」课时是免费的吗?

是的 — 「带数据的枚举」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「带数据的枚举」这节课中我会学到什么?

为变体附加值。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「带数据的枚举」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义您的第一个枚举
  2. 匹配枚举变体
  3. 带数据的枚举
  4. 匹配守卫和绑定
← 返回 Learn Rust Coding