====== 结构体、枚举与模式匹配 ====== ===== 结构体(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'' 表示值存在或不存在: enum Option { Some(T), None, } fn main() { let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option = None; // 使用 Option 时需要显式处理 None let x: i8 = 5; let y: Option = Some(5); // let sum = x + y; // 编译错误:Option 和 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 ==== fn plus_one(x: Option) -> Option { 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'' 替代空值,强制处理 ''None'' 情况 * ''match'' 必须穷举所有分支,''_'' 通配符处理剩余情况