Rust 기초부터 마스터까지 — 4화
구조체와 enum으로 유효한 상태 표현하기
본 블로그 작성 글들은, 강의를 목표로 하고 제작되었습니다. 또한 작성된 글의 정보도 틀렸을 수 있으니, 주의해주세요.
구조체는 관련 데이터를 묶고 enum은 가능한 상태를 나열한다. 둘을 함께 사용하면 존재할 수 없는 조합을 필드와 bool로 억지로 표현하지 않아도 된다.
구조체와 impl
struct Player {
name: String,
health: i32,
}
impl Player {
fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
health: 100,
}
}
fn take_damage(&mut self, amount: i32) {
self.health = (self.health - amount.max(0)).max(0);
}
}
impl 블록은 구조체와 관련된 생성 함수와 메서드를 정의한다. &mut self는 메서드가 객체를 변경하기 위해 독점적으로 빌린다는 뜻이다.
enum으로 상태 표현하기
enum QuestState {
Locked,
Active { progress: u32, goal: u32 },
Completed { reward_claimed: bool },
}
Active일 때만 progress가 있고 Completed일 때만 보상 수령 상태가 있다. 여러 bool과 nullable 필드로 같은 정보를 표현할 때보다 잘못된 조합이 줄어든다.
패턴 매칭
fn describe(state: &QuestState) -> String {
match state {
QuestState::Locked => String::from("Locked"),
QuestState::Active { progress, goal } => {
format!("{progress}/{goal}")
}
QuestState::Completed { reward_claimed: true } => {
String::from("Reward claimed")
}
QuestState::Completed { reward_claimed: false } => {
String::from("Reward ready")
}
}
}
match는 enum의 모든 경우를 처리했는지 검사한다. 새 상태를 추가하면 처리하지 않은 코드가 컴파일 오류로 드러난다.
Option과 Result도 같은 enum이다. Rust에서는 상태와 실패 가능성을 타입으로 표현하고 match나 전용 메서드로 각 경우를 처리한다.