Menu
Coddy logo textTech

Setter

Coddy Rust 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 61개 중 12번째.

Getter를 사용하면 외부 코드가 private 데이터를 read할 수 있습니다. 하지만 데이터를 변경할 수 있도록 해야 한다면 어떻게 해야 할까요? 바로 setter 메서드가 필요한 경우입니다. setter 메서드는 private 필드를 제어된 방식으로 수정하는 public 메서드입니다.

기본 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는 음수가 될 수 없습니다. 이것이 바로 캡슐화가 작동하는 방식입니다. 구조체가 자체 불변 조건을 제어하므로 외부 코드는 이를 Invalid 상태로 만들 수 없습니다.

challenge icon

챌린지

쉬움

setter가 데이터를 유효하게 유지하기 위해 규칙을 적용하는 방식을 보여 주는 thermostat 시스템을 만들어 보겠습니다. thermostat에는 안전한 범위 내에서만 조정할 수 있는 temperature setting이 있습니다.

코드를 정리하기 위해 두 개의 파일을 만듭니다:

  • thermostat.rs: private temperature field가 있는 Thermostat struct를 Define합니다 (i32). struct는 public이어야 하지만, 잘못된 값으로부터 보호하기 위해 field는 private으로 유지됩니다. 다음을 Implement합니다:
    • initial temperature를 받는 new constructor
    • current temperature를 returns하는 temperature getter
    • 10에서 30 (inclusive) 사이의 값만 허용하는 set_temperature setter. 값이 이 range outside에 있으면 temperature는 변경되지 않은 상태로 유지되어야 합니다.
  • main.rs: thermostat module을 가져오고, thermostat을 만들고, 다양한 temperature를 설정하려고 시도한 뒤 각 Attempt 후 result를 출력하여 setter의 검증을 보여 줍니다.

setter는 Invalid 값을 조용히 무시해야 합니다. 즉, error message를 출력하지 않고, 유효한 range outside의 값을 설정하려고 하면 current temperature를 그대로 유지합니다.

출력은 다음 정확한 형식을 따라야 합니다:

Initial: {temperature}
After setting to {attempted_value}: {temperature}
After setting to {attempted_value}: {temperature}

예를 들어 thermostat을 20으로 Create한 다음 25(유효함)로 설정하려고 하고, 이어서 50(유효하지 않음)으로 설정하려고 하면 출력은 다음과 같습니다:

Initial: 20
After setting to 25: 25
After setting to 50: 25

세 개의 inputs를 받습니다. initial temperature, Attempt할 first temperature, 그리고 Attempt할 second temperature입니다.

직접 해보기

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: 첫 번째 온도 설정을 시도하고 결과 출력
    // Format: "After setting to {attempted_value}: {temperature}"

    // TODO: 두 번째 온도 설정을 시도하고 결과 출력
    // Format: "After setting to {attempted_value}: {temperature}"
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Rust 컴파일러