结构体、枚举与模式匹配
结构体(Struct)
定义结构体
struct User { username: String, email: String, sign_in_count: u64, active: bool, }
创建实例
fn main() { let user = User { username: String::from("小明"), email: String::from("xiaoming@example.com"), sign_in_count: 1, active: true, }; }
修改字段
需要整个实例可变(Rust 不支持单独字段可变):
fn main() { let mut user = User { username: String::from("小明"), email: String::from("xiaoming@example.com"), sign_in_count: 1, active: true, }; user.email = String::from("new_email@example.com"); }
结构体构造简写
fn build_user(username: String, email: String) -> User { User { username, // 字段名与参数名相同时可简写 email, // 相当于 email: email sign_in_count: 1, active: true, } }
结构体更新语法
fn main() { let user1 = User { username: String::from("小明"), email: String::from("a@example.com"), sign_in_count: 1, active: true, }; let user2 = User { email: String::from("b@example.com"), ..user1 // 其余字段从 user1 复制 }; }
元组结构体
struct Color(i32, i32, i32); struct Point(i32, i32, i32); fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); // black 和 origin 是不同的类型 }
单元结构体
没有字段的结构体,用于实现 trait:
struct UnitStruct; fn main() { let u = UnitStruct; }
方法
在 impl 块中定义方法:
struct Rectangle { width: u32, height: u32, } impl Rectangle { // 方法:&self 是 self: &Self 的语法糖 fn area(&self) -> u32 { self.width * self.height } // 方法:多参数 fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } // 关联函数(静态方法) fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } fn main() { let rect = Rectangle { width: 30, height: 50 }; println!("面积: {}", rect.area()); let sq = Rectangle::square(10); // 关联函数用 :: 调用 }
枚举
定义枚举
enum IpAddr { V4, V6, } fn main() { let four = IpAddr::V4; let six = IpAddr::V6; }
枚举带数据
枚举成员可以携带不同类型的数据:
enum IpAddr { V4(u8, u8, u8, u8), V6(String), } enum Message { Quit, // 无数据 Move { x: i32, y: i32 }, // 命名成员 Write(String), // 元组 ChangeColor(i32, i32, i32), // 元组 } fn main() { let home = IpAddr::V4(127, 0, 0, 1); let msg = Message::Write(String::from("hello")); }
Option 枚举
Rust 没有空值(null),用 Option<T> 表示值存在或不存在:
enum Option<T> { Some(T), None, } fn main() { let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option<i32> = None; // 使用 Option 时需要显式处理 None let x: i8 = 5; let y: Option<i8> = Some(5); // let sum = x + y; // 编译错误:Option<i8> 和 i8 不能直接相加 }
match 模式匹配
匹配枚举
enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }
匹配 Option<T>
fn plus_one(x: Option<i32>) -> Option<i32> { match x { None => None, Some(i) => Some(i + 1), } } fn main() { let five = Some(5); let six = plus_one(five); let none = plus_one(None); }
匹配必须穷举
match 必须覆盖所有可能。_ 通配符匹配所有剩余情况:
fn main() { let num = 0u32; match num { 1 => println!("一"), 2 => println!("二"), 3 => println!("三"), _ => println!("其他数字"), // 必须包含,否则编译错误 } }
本章实践
#[derive(Debug)] enum UsState { Sichuan, Guangdong, // ... } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn describe_coin(coin: &Coin) -> String { match coin { Coin::Penny => "1 分".to_string(), Coin::Nickel => "5 分".to_string(), Coin::Dime => "10 分".to_string(), Coin::Quarter(state) => { format!("25 分(来自 {:?})", state) } } } fn main() { let my_coin = Coin::Quarter(UsState::Sichuan); println!("{}", describe_coin(&my_coin)); }
本章小结
- 结构体有三种:命名结构体、元组结构体、单元结构体
impl块为结构体定义方法- 枚举可以附带任意类型的数据
Option<T>替代空值,强制处理None情况match必须穷举所有分支,_通配符处理剩余情况