Setter
Coddy Rust 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 12번째.
게터(Getters)는 외부 코드에서 비공개 데이터를 읽을 수 있게 해줍니다. 하지만 외부에서 데이터를 변경하도록 허용해야 한다면 어떨까요? 바로 여기서 세터 메서드(setter methods)가 등장합니다. 이는 비공개 필드를 제어된 방식으로 수정하는 공개 메서드입니다.
기본적인 세터(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;
}
// 음수 값은 자동으로 무시됩니다
}
이제 지갑은 스스로를 보호합니다. 외부 코드에서 어떤 값을 설정하려고 시도하더라도, balance는 결코 음수가 될 수 없습니다. 이것이 바로 캡슐화(encapsulation)가 실제로 작동하는 방식입니다. struct가 스스로의 불변성(invariants)을 제어하며, 외부 코드는 단순히 그것을 유효하지 않은 상태로 만들 수 없습니다.
챌린지
쉬움데이터의 유효성을 유지하기 위해 세터(setter)가 어떻게 규칙을 강제할 수 있는지 보여주는 온도 조절기 시스템을 만들어 보겠습니다. 여러분의 온도 조절기에는 안전한 범위 내에서만 조정할 수 있는 온도 설정 기능이 있습니다.
코드를 정리하기 위해 두 개의 파일을 생성합니다:
thermostat.rs: 비공개(private)temperature필드(i32)를 가진Thermostat구조체를 정의합니다. 구조체는 공개(public)되어야 하지만, 필드는 잘못된 값으로부터 보호하기 위해 비공개로 유지합니다. 다음을 구현하세요:- 초기 온도를 매개변수로 받는
new생성자 - 현재 온도를 반환하는
temperature게터(getter) - 10에서 30 사이(포함)의 값만 허용하는
set_temperature세터. 값이 이 범위를 벗어나면 온도는 변경되지 않고 그대로 유지되어야 합니다.
- 초기 온도를 매개변수로 받는
main.rs: 온도 조절기 모듈을 가져와서 온도 조절기 인스턴스를 생성하고, 다양한 온도로 설정을 시도한 후 매 시도마다 결과를 출력하여 세터의 유효성 검사를 시연합니다.
세터는 유효하지 않은 값을 조용히 무시해야 합니다. 즉, 에러 메시지를 출력하지 않고, 유효 범위를 벗어난 값으로 설정을 시도할 때 현재 온도를 변경하지 않고 그대로 유지합니다.
출력은 반드시 다음 형식을 따라야 합니다:
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세 개의 입력을 받게 됩니다: 초기 온도, 첫 번째 시도할 온도, 그리고 두 번째 시도할 온도입니다.
치트 시트
Setter 메서드는 외부 코드에서 비공개 필드를 제어된 방식으로 수정할 수 있도록 합니다. 이 메서드들은 구조체의 데이터를 변경할 수 있는 권한을 얻기 위해 &mut self를 매개변수로 받습니다.
기본적인 setter 구문:
pub fn set_balance(&mut self, amount: f64) {
self.balance = amount;
}Rust의 setter는 일반적으로 데이터를 수정한다는 것을 명확히 나타내기 위해 set_ 접두사를 사용합니다.
Setter를 사용하면 규칙을 강제하고 데이터 무결성을 유지하기 위한 검증(validation)이 가능해집니다:
pub fn set_balance(&mut self, amount: f64) {
if amount >= 0.0 {
self.balance = amount;
}
// 유효하지 않은 값은 자동으로 무시됩니다.
}이것이 바로 캡슐화의 실제 사례입니다. 구조체가 스스로의 불변성(invariants)을 제어하여, 외부 코드가 구조체를 유효하지 않은 상태로 만드는 것을 방지합니다.
직접 해보기
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: 초기 온도로 온도 조절기(thermostat) 생성
// TODO: 초기 온도 출력
// 형식: "Initial: {temperature}"
// TODO: 첫 번째 온도 설정을 시도하고 결과 출력
// 형식: "After setting to {attempted_value}: {temperature}"
// TODO: 두 번째 온도 설정을 시도하고 결과 출력
// 형식: "After setting to {attempted_value}: {temperature}"
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.