Menu
CoddyTech

多个实现块

本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 5 课,共 61 课。

Rust 允许你将结构体的方法拆分到多个 impl 块中。虽然所有内容都可以放在一个块中,但将它们分开能让代码更有条理、更易读。

下面是一个结构体,它的功能分散在两个实现块中:

struct BankAccount {
    balance: f64,
}

// 构造函数和基本查询
impl BankAccount {
    fn new(initial: f64) -> BankAccount {
        BankAccount { balance: initial }
    }
    
    fn balance(&self) -> f64 {
        self.balance
    }
}

// 交易方法
impl BankAccount {
    fn deposit(&mut self, amount: f64) {
        self.balance += amount;
    }
    
    fn withdraw(&mut self, amount: f64) {
        self.balance -= amount;
    }
}

这两个代码块配合得天衣无缝:Rust 会把它们当作一个整体。无论方法定义在哪个代码块中,你都可以调用它:

fn main() {
    let mut account = BankAccount::new(100.0);
    account.deposit(50.0);
    println!("{}", account.balance()); // 150
}

随着结构体变得越来越复杂,这种模式会特别有用。你可以把构造函数放在一起,将只读方法和会修改数据的方法分开,或者按功能组织。一个结构体可以有任意多个 impl 块。

challenge icon

挑战

简单

创建一个 Player 结构体,包含两个字段:name(String)和 score(u32)。

将结构体的方法分布在两个单独的实现块中:

第一个 impl 块:构造函数和查询方法:

  • new:一个关联函数,接受 name: String,并返回一个 score 设置为 0 的 Player
  • get_score:接受 &self,并以 u32 返回当前分数

第二个 impl 块:修改分数:

  • add_points:接受 &mut self 和 points: u32,将这些分数加到当前分数上
  • reset_score:接受 &mut self,并将分数重置为 0

你会收到 3 个输入:

  • 第一行:玩家的名字(String)
  • 第二行:第一轮要增加的分数(u32)
  • 第三行:第二轮要增加的分数(u32)

使用 Player::new 创建一个玩家,增加第一轮的分数并打印分数,然后重置分数,增加第二轮的分数,并打印最终分数。

预期输出格式:

{score_after_first_round}
{score_after_reset_and_second_round}

亲手试试

use std::io;

// TODO:定义 Player 结构体,包含 name(String)和 score(u32)字段


// TODO:第一个 impl 块,包含构造方法和查询方法(new、get_score)


// TODO:第二个 impl 块,包含修改分数的方法(add_points、reset_score)


fn main() {
    let mut input = String::new();
    
    // 读取玩家姓名
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let name = input.trim().to_string();
    
    // 读取第一轮得分
    input.clear();
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let first_round: u32 = input.trim().parse().expect("Invalid number");
    
    // 读取第二轮得分
    input.clear();
    io::stdin().read_line(&mut input).expect("Failed to read line");
    let second_round: u32 = input.trim().parse().expect("Invalid number");
    
    // TODO:使用 Player::new 创建玩家
    // TODO:加上第一轮得分并输出分数
    // TODO:重置分数
    // TODO:加上第二轮得分并输出最终分数
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Rust 在线编译器