结构体与方法
你会学到什么
- 用
struct把相关字段组合成一个类型。 - 用
impl块定义方法(带self)和关联函数(不带self)。 - 用
#[derive(...)]自动获得Debug、Clone、PartialEq等能力。
最小示例
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
运行代码
cd examples
cargo run -p rt_10_structs
cargo test -p rt_10_structs
代码讲解
关联函数常用作构造器,用 Self 指代当前类型:
fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
方法的第一个参数是 &self(只读)、&mut self(可修改)或 self(消费所有权)。
#[derive(Debug, Clone, PartialEq)] 让结构体能被 {:?} 打印、.clone() 复制、用 == 比较,省去手写样板代码。
常见错误
忘记 & 直接写 self,会意外消费所有权:
impl Rectangle {
fn area(self) -> u32 { // 调用后 rectangle 被移动
self.width * self.height
}
}
只读方法几乎总是用 &self。
练习
- 给
Rectangle加一个can_hold(&self, other: &Rectangle) -> bool。 - 加一个关联函数
square(size: u32) -> Rectangle。
小结
结构体是 Rust 建模的基本单元,方法和关联函数组织行为,derive 自动生成常用 trait 实现。
下一步
当数据有“多种形态”时,枚举比结构体更合适。下一章学习枚举与 Option。
完整示例代码
下面是 examples/10_structs/ 的完整源码。无需 clone 仓库,直接在页面上阅读、复制、对照运行。
examples/10_structs/src/main.rs
//! 结构体、方法与关联函数。
#[derive(Debug, Clone, PartialEq)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
/// 关联函数(无 self),常用作构造器。
fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
/// 方法(带 &self),只读访问字段。
fn area(&self) -> u32 {
self.width * self.height
}
fn is_square(&self) -> bool {
self.width == self.height
}
/// 返回一个新结构体,不修改自身。
fn scaled(&self, factor: u32) -> Self {
Self::new(self.width * factor, self.height * factor)
}
}
fn main() {
let rect = Rectangle::new(3, 4);
println!("{rect:?}");
println!("area = {}", rect.area());
println!("is_square = {}", rect.is_square());
println!("scaled = {:?}", rect.scaled(2));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn computes_area() {
assert_eq!(Rectangle::new(3, 4).area(), 12);
}
#[test]
fn detects_square() {
assert!(Rectangle::new(5, 5).is_square());
assert!(!Rectangle::new(5, 6).is_square());
}
#[test]
fn scales_into_new_value() {
let rect = Rectangle::new(2, 3);
assert_eq!(rect.scaled(2), Rectangle::new(4, 6));
// 原值不变。
assert_eq!(rect, Rectangle::new(2, 3));
}
} examples/10_structs/Cargo.toml
[package]
name = "rt_10_structs"
version.workspace = true
edition.workspace = true
publish.workspace = true