设置方法
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 12 课,共 61 课。
Getter 允许外部代码读取私有数据。但如果你需要让外部代码修改数据,该怎么办?这时就需要setter 方法:通过受控的方式修改私有字段的公共方法。
基本的 setter 接受 &mut self 和一个新值:
// wallet.rs
pub struct Wallet {
balance: f64,
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Self { balance: initial }
}
pub fn balance(&self) -> f64 {
self.balance
}
pub fn set_balance(&mut self, amount: f64) {
self.balance = amount;
}
}
与 getter 不同,Rust 的 setter 通常使用 set_ 前缀,以清楚地表明它们会修改数据。&mut self 参数必不可少。它赋予方法修改结构体字段的权限。
setter 的真正作用是验证。你可以设定规则,而不是盲目接受任何值:
pub fn set_balance(&mut self, amount: f64) {
if amount >= 0.0 {
self.balance = amount;
}
// 负值会被直接忽略,不会提示。
}
现在,钱包可以保护自己:无论外部代码尝试设置什么值,余额都不会变成负数。这就是封装的实际应用:结构体维护自身的不变条件,外部代码无法让它进入无效状态。
挑战
简单我们来构建一个恒温器系统,演示 setter 如何通过强制执行规则来确保数据有效。你的恒温器会有一个温度设置,只能在安全范围内调整。
你将创建两个文件来组织代码:
thermostat.rs:定义一个Thermostat结构体,其中包含一个私有的temperature字段(i32)。结构体应为公开的,但字段应保持私有,以防止出现无效值。实现以下内容:- 一个
new构造函数,用于接收初始温度 - 一个
temperaturegetter,用于返回当前温度 - 一个
set_temperaturesetter,只接受 10 到 30 之间的值(含边界)。如果值超出此范围,温度应保持不变。
- 一个
main.rs:引入你的恒温器模块,创建一个恒温器,并尝试设置不同的温度,演示 setter 的验证功能,每次尝试后都打印结果。
setter 应静默忽略无效值:不要显示错误消息,当有人尝试将温度设置为有效范围之外的值时,只需保持当前温度不变。
你的输出应严格遵循以下格式:
Initial: {temperature}
After setting to {attempted_value}: {temperature}
After setting to {attempted_value}: {temperature}例如,如果你将恒温器的初始温度设为 20,然后尝试将温度设为 25(有效),再设为 50(无效),输出应为:
Initial: 20
After setting to 25: 25
After setting to 50: 25你将收到三个输入:初始温度、第一次尝试设置的温度,以及第二次尝试设置的温度。
亲手试试
mod thermostat;
use thermostat::Thermostat;
fn main() {
// 读取输入
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_temp: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let first_attempt: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let second_attempt: i32 = input3.trim().parse().expect("Invalid number");
// TODO:用初始温度创建一个恒温器
// TODO:输出初始温度
// 格式:"Initial: {temperature}"
// TODO:尝试设置第一次输入的温度,并输出结果
// 格式:"After setting to {attempted_value}: {temperature}"
// TODO:尝试设置第二次输入的温度,并输出结果
// 格式:"After setting to {attempted_value}: {temperature}"
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器