10·复合类型入门

结构体(Struct)

结构体(Struct)

学习目标

  1. 定义和实例化结构体
  2. 掌握方法(impl)定义
  3. 理解关联函数
  4. 掌握元组结构体和单元结构体

核心概念

定义结构体

struct User {
    username: String,
    email: String,
    age: u32,
    active: bool,
}

fn main() {
    let user = User {
        username: String::from("rustacean"),
        email: String::from("rust@example.com"),
        age: 25,
        active: true,
    };

    println!("{} 的邮箱是 {}", user.username, user.email);
}

可变结构体

fn main() {
    let mut user = User {
        username: String::from("alice"),
        email: String::from("alice@example.com"),
        age: 30,
        active: true,
    };

    user.email = String::from("new@example.com");  // 整个实例必须是 mut
}

结构体更新语法

fn main() {
    let user1 = User {
        username: String::from("alice"),
        email: String::from("alice@example.com"),
        age: 30,
        active: true,
    };

    // 基于 user1 创建 user2,只覆盖部分字段
    let user2 = User {
        username: String::from("bob"),
        email: String::from("bob@example.com"),
        ..user1  // 其余字段从 user1 复制/移动
    };
    // 注意:user1.username 和 user1.email 已被移动,user1.age 和 user1.active 是 Copy,仍有效
}

方法(impl)

struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    // 方法:第一个参数是 &self
    fn area(&self) -> f64 {
        self.width * self.height
    }

    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }

    // 可变方法
    fn scale(&mut self, factor: f64) {
        self.width *= factor;
        self.height *= factor;
    }

    // 消费 self:调用后实例失效
    fn into_square(self) -> Rectangle {
        let side = self.width.max(self.height);
        Rectangle { width: side, height: side }
    }
}

fn main() {
    let mut rect = Rectangle { width: 10.0, height: 5.0 };
    println!("面积: {}", rect.area());
    println!("周长: {}", rect.perimeter());

    rect.scale(2.0);
    println!("放大后面积: {}", rect.area());
}

关联函数(不带 self)

impl Rectangle {
    // 关联函数:没有 self 参数,类似其他语言的静态方法
    fn new(width: f64, height: f64) -> Self {
        Rectangle { width, height }
    }

    fn square(size: f64) -> Self {
        Rectangle { width: size, height: size }
    }
}

fn main() {
    let rect = Rectangle::new(10.0, 5.0);  // 用 :: 调用
    let sq = Rectangle::square(7.0);
}

元组结构体

struct Color(u8, u8, u8);
struct Point(f64, f64, f64);

fn main() {
    let red = Color(255, 0, 0);
    let origin = Point(0.0, 0.0, 0.0);

    println!("R={}, G={}, B={}", red.0, red.1, red.2);
}

单元结构体

struct Marker;  // 没有字段,用于 trait 实现或标记

impl Marker {
    fn mark(&self) {
        println!("marked!");
    }
}

Debug 和 Display

// 自动派生 Debug
#[derive(Debug)]
struct Point {
    x: f64,
    y: f64,
}

fn main() {
    let p = Point { x: 1.0, y: 2.0 };
    println!("{:?}", p);    // Point { x: 1.0, y: 2.0 }
    println!("{:#?}", p);   // 带格式化的 Debug 输出
}

实践练习

练习 1:学生管理

#[derive(Debug)]
struct Student {
    name: String,
    grade: u32,
    scores: Vec<f64>,
}

impl Student {
    fn new(name: &str, grade: u32) -> Self {
        Student {
            name: String::from(name),
            grade,
            scores: Vec::new(),
        }
    }

    fn add_score(&mut self, score: f64) {
        self.scores.push(score);
    }

    fn average(&self) -> f64 {
        if self.scores.is_empty() {
            return 0.0;
        }
        self.scores.iter().sum::<f64>() / self.scores.len() as f64
    }
}

fn main() {
    let mut alice = Student::new("Alice", 3);
    alice.add_score(95.0);
    alice.add_score(87.0);
    alice.add_score(92.0);
    println!("{:?}, 平均分: {:.1}", alice, alice.average());
}

练习 2:链表节点

#[derive(Debug)]
struct Node {
    value: i32,
    next: Option<Box<Node>>,
}

impl Node {
    fn new(value: i32) -> Self {
        Node { value, next: None }
    }

    fn push(&mut self, value: i32) {
        match &mut self.next {
            Some(node) => node.push(value),
            None => self.next = Some(Box::new(Node::new(value))),
        }
    }

    fn to_vec(&self) -> Vec<i32> {
        let mut result = vec![self.value];
        if let Some(next) = &self.next {
            result.extend(next.to_vec());
        }
        result
    }
}

fn main() {
    let mut head = Node::new(1);
    head.push(2);
    head.push(3);
    println!("{:?}", head.to_vec());  // [1, 2, 3]
}

常见错误

1. 忘记字段

let user = User {
    username: String::from("alice"),
    email: String::from("alice@example.com"),
    // ❌ 缺少 age 和 active 字段
};

2. 可变性

let user = User { /* ... */ };
// user.age = 26;  // ❌ user 不是 mut

3. 生命周期

// ❌ 结构体持有引用需要生命周期
struct Excerpt {
    text: &str,
}

// ✅
struct Excerpt<'a> {
    text: &'a str,
}

小结

概念语法
定义struct Name { field: Type }
实例化Name { field: value }
方法impl Name { fn method(&self) {} }
关联函数impl Name { fn new() -> Self {} }
更新语法..other
Debug#[derive(Debug)]

练习编辑器

rust
Loading...