====== 结构体、枚举与模式匹配 ======
===== 结构体(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'' 必须穷举所有分支,''_'' 通配符处理剩余情况