Menu
CoddyTech

私有字段

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

在上一课中,你把所有内容都设为公开:结构体、它的字段和方法。但真正的封装意味着控制数据的访问方式。在 Rust 中,你可以让结构体公开,同时将它的字段设为私有。

考虑一个 Wallet,它的余额永远不应为负数。如果字段是公开的,任何人都可以将它设为任意值:

// wallet.rs
pub struct Wallet {
    balance: f64,  // 没有 pub 就是私有的!
}

impl Wallet {
    pub fn new(initial: f64) -> Wallet {
        Wallet { balance: initial }
    }
}

注意,Wallet 是公开的,但 balance 没有 pub 关键字。这意味着模块外的代码可以使用构造函数创建 Wallet,但不能直接读取或修改余额字段:

// main.rs
mod wallet;
use wallet::Wallet;

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // 错误!字段是私有的
    // w.balance = -50.0;          // 错误!无法访问私有字段
}

这就是封装的基础:结构体控制自己的数据。外部代码必须通过你提供的方法来访问数据,这意味着你可以添加验证、日志记录或其他逻辑。这样可以保护数据,使其不会处于无效状态。

在接下来的课程中,你将学习如何通过 getter 和 setter 方法来受控地访问这些私有数据。

challenge icon

挑战

简单

让我们构建一个温度传感器系统,通过将敏感数据保存在模块中来演示封装。

你将创建两个文件来组织代码:

  • sensor.rs:定义一个 TemperatureSensor 结构体,包含两个字段:location(String)和 reading(f64)。结构体应设为公开,以便其他文件可以使用它,但两个字段都要保持私有:外部代码不能直接访问或修改传感器的数据。添加一个公开的 new 构造函数,接收位置名称和初始温度读数。
  • main.rs:引入传感器模块,并使用构造函数创建一个 TemperatureSensor。由于字段是私有的,你不能直接打印它们,而应打印一条确认消息,说明传感器已成功创建。

这个挑战侧重于私有字段这一核心概念:结构体可以访问,但其内部数据受到保护。外部代码只能通过你提供的方法与传感器交互(在本例中,只有构造函数)。

你的输出应严格遵循以下格式:

Sensor created for: {location}

要访问位置并打印出来,你需要让 new 函数在返回传感器之前打印这条消息,因为字段本身是私有的。

例如,如果你创建一个位置为 "Kitchen"、读数为 22.5 的传感器,输出将是:

Sensor created for: Kitchen

你将收到两个输入:位置名称和初始温度读数。

亲手试试

mod sensor;

use sensor::TemperatureSensor;

fn main() {
    // 读取输入
    let mut location = String::new();
    std::io::stdin().read_line(&mut location).expect("Failed to read line");
    let location = location.trim().to_string();
    
    let mut reading_str = String::new();
    std::io::stdin().read_line(&mut reading_str).expect("Failed to read line");
    let reading: f64 = reading_str.trim().parse().expect("Failed to parse reading");
    
    // TODO: 用构造函数创建一个 TemperatureSensor
    // new 函数会负责打印确认消息
    
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Rust 在线编译器