学习 Rust 的第十天:枚举和模式匹配

发布于:2024-04-28 ⋅ 阅读:(32) ⋅ 点赞:(0)

大家好,

今天是学习 Rust 的第十天。昨天我们讨论了如何使用 structs 将相关数据分组在一起。今天我们来看一个类似的概念,即 enums

导论

Rust 中的枚举是一种数据类型,允许你通过列举可能的值来定义类型,提供了一种简洁而类型安全的方式来表示不同的选择。

enum Day {  
  Monday,  
  Tuesday,  
  Wednesday,  
  Thursday,  
  Friday,  
  Saturday,  
  Sunday,  
}  
  
fn main() {  
  let today = Day::Monday;  
}

这就是 enums 的基本概念……

如果我们要用编程语言来存储每一天要学习 Rust 的情况。我们会像这样使用 structs

enum Day {  
  Monday,  
  Tuesday,  
  Wednesday,  
  Thursday,  
  Friday,  
  Saturday,  
  Sunday,  
}  
  
struct TimeTable {  
  day: Day,  
  language: String,  
}  
  
fn main() {  
  let day1 = TimeTable {  
    day: Day::Monday,  
    language: String::from("Rust"),  
  };  
}

另一种方式是将值存储在 enums 中。

enum Day {  
  Monday(String),  
  Tuesday(String),  
  Wednesday(String),  
  Thursday(String),  
  Friday(String),  
  Saturday(String),  
  Sunday(String),  
}  
  
struct TimeTable {  
  day: Day,  
  language: String,  
}  
  
fn main() {  
  let day1 = Day::Monday(String::from("Rust"));  
}

枚举中的方法

就像我们为 structs 做的那样,我们可以创建一个 impl 块来在 enums 中实现方法。

// 定义一个枚举叫做 Shape 代表不同的几何形状  
enum Shape {  
    Circle(f64), // 变体 Circle 接受一个半径  
    Square(f64), // 变体 Square 接受一个边长  
}  
  
// 在 Shape 枚举上实现方法  
impl Shape {  
    // 计算形状的面积的方法  
    fn area(&self) -> f64 {  
        match *self {  
            Shape::Circle(radius) => 3.14 * radius * radius,  
            Shape::Square(side_length) => side_length * side_length,  
        }  
    }  
}  
  
fn main() {  
    // 创建不同形状的实例  
    let circle = Shape::Circle(2.0);  
    let square = Shape::Square(3.0);  
  
    // 计算并打印不同形状的面积  
    println!("圆的面积: {:.2}", circle.area());  
    println!("正方形的面积: {:.2}", square.area());  
}

输出:

圆的面积: 12.57  
正方形的面积: 9.00

解释

  • 我们定义了一个枚举名为 Shape,代表几何形状。
  • Shape 有两种变体: Circle(f64),表示带有半径的圆,和 Square(f64),表示带有边长的正方形。
  • Shape 枚举实现了一个叫做 area() 的方法。
  • area() 方法接受一个对 self(枚举实例)的引用,并返回一个表示形状面积的 f64。
  • Rust 中的 match 关键字允许根据匹配的模式执行代码,提供了一种简洁而强大的处理不同情况或枚举、结构体等类型变体的方式。
  • 对于 Shape::Circle,它使用公式 π * 半径^2 计算面积。
  • 对于 Shape::Square,它使用公式 边长^2 计算面积。
  • 在 main() 函数中:
  • 创建了不同形状的实例(circle 和 square)。
  • 在每个形状实例上调用 area() 方法来计算和打印它们各自的面积。
  • 最后,使用 println!() 语句以两位小数打印圆和正方形的面积。

Option 枚举

Rust 中的 Option enum 表示值的存在或不存在,提供了一种简洁而类型安全的方式来处理可能存在或缺失值的情况。

如果我们有一个可能为空值的值,Rust 并没有 null 类型,我们可以使用 Option 枚举来处理这些情况。

这样做可以强制类型系统要求我们处理空值情况,从而使代码更安全。

  • Some 用于值存在时
  • None 用于值不存在时
  • 从这里,我们可以使用 match 操作来列举这两种情况。
fn get_first_element(numbers: &[i32]) -> Option<i32> {  
    if let Some(&first) = numbers.first() {  
        Some(first) // 如果存在,返回 Some 包裹的第一个元素  
    } else {  
        None // 如果切片为空,则返回 None  
    }  
}

解释

  • get_first_element 函数以整数切片 numbers 作为参数。
  • 它使用切片的 .first() 方法来获取一个包含切片第一个元素的 Option。
  • 如果切片不为空,.first() 返回 Some(&first),其中 first 是对第一个元素的引用。

该函数对 Option 进行模式匹配:

  • 如果 Option 是 Some,它提取 first 的值并将其包装在另一个 Some 中,有效地解包引用。
  • 如果 Option 是 None,表示切片为空,则返回 None

使用 Option 枚举处理基本数据类型

fn main() {  
  let x: i8 = 10;  
  let y: Option<i8> = Some(14);  
    
  let sum = x + y;  
}

这段代码会导

致错误,因为我们不能将 i8 加到 Option<i8>,因为它们是不同的数据类型。

为了完成这个操作,我们可以使用 unwrap_or() 方法。

unwrap_or(data) 如果存在,则返回 Option enum 的值,如果不存在,则返回 data

fn main() {  
  let x: i8 = 10;  
  let y: Option<i8> = Some(14);  
  let sum = x + y.unwrap_or(0);  
  println!("{}", sum);  
}

输出:

24

模式匹配

我们在猜数字游戏中使用了 match,它用于检查多种情况并针对每个值运行特定的代码块。

这是一个简单的例子:

fn main() {  
    let number = 5;  
  
    match number {  
        1 => println!("It's one!"),  
        2 => println!("It's two!"),  
        3 | 4 => println!("It's three or four!"),  
        8 => {  
          println!("This is a multi-line function in a match expression");  
        },  
        _ => println!("It's something else!"),  
    }  
}
  • 使用 match 关键字对 number 的值进行模式匹配。
  • match 表达式中的每个模式后面都跟着 =>,指示匹配模式时要执行的代码。
  • 如果 number 匹配模式 1,则打印消息 “It’s one!”。
  • 如果 number 匹配模式 2,则打印消息 “It’s two!”。
  • 如果 number 匹配模式 34,则打印消息 “It’s three or four!”。
  • 如果 number 匹配模式 8,则执行大括号内的代码,打印 “This is a multi-line function in a match expression”。
  • _ 模式充当通配符,匹配任何未明确列出的值。如果 number 不匹配任何指定的模式,则使用通配符模式 _,并打印消息 “It’s something else!”。

在这个具体例子中,由于 number5,它不匹配任何特定模式,因此使用通配符模式 _,并打印消息 “It’s something else!”。

结论

在学习 Rust 的第十天,我们深入探讨了枚举和模式匹配。以下是我们讨论的内容摘要:

  • 枚举:我们看到在 Rust 中,枚举是一种列出可能值的数据类型,提供了一种简单而类型安全的方式来描述选择。我们探讨了如何创建枚举以及如何使用它们来表示类似的可能性,比如一周的天数。
  • 枚举中的方法:与结构体类似,我们看到我们可以使用 impl 块在枚举上实现方法。我们通过创建计算不同几何形状面积的方法来演示了这一点,这些形状由枚举表示。
  • Option 枚举:我们讨论了 Option 枚举,它通常用于处理值可能存在或不存在的情况。我们探讨了 Some 表示值存在,而 None 表示值不存在。此外,我们学习了如何使用 unwrap_or 方法来处理我们需要从 Option 中提取值或者在值不存在时提供默认值的情况。
  • 模式匹配:最后,我们探讨了使用 match 关键字进行模式匹配,它允许我们检查多种情况并根据匹配的模式执行特定的代码。我们演示了如何使用 match 来处理各种情况并执行相应的代码块。