기본 구현 오버라이딩
Coddy Rust 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 32번째.
기본 구현은 편리하지만, 때로는 타입이 표준과 다른 동작을 필요로 할 때가 있습니다. 이런 경우, impl 블록에 직접 구현을 제공함으로써 기본값을 재정의(override)할 수 있습니다.
동일한 시그니처로 메서드를 정의하되, 사용자 정의 로직을 포함하기만 하면 됩니다:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
Greet가 기본 greet 메서드를 제공하더라도, Robot은 이를 자신의 버전으로 완전히 대체합니다. Robot에서 greet()를 호출하면, Rust는 사용자 정의 구현을 사용합니다:
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // BEEP BOOP. 유닛 42 온라인.
이것은 유연성을 제공합니다. 기본 동작으로 충분한 타입은 아무것도 작성할 필요가 없으며, 특수한 동작이 필요한 타입은 관심 있는 메서드만 오버라이드할 수 있습니다. 트레이트는 여전히 이를 구현하는 모든 타입이 해당 메서드를 사용할 수 있음을 보장합니다.
챌린지
쉬움다양한 알림 유형이 메시지를 맞춤 설정할 수 있는 알림 시스템을 만들어 봅시다! 기본 구현이 포함된 트레이트(trait)를 생성한 다음, 한 유형은 기본 구현을 사용하고 다른 유형은 사용자 정의 동작으로 이를 오버라이드하도록 할 것입니다.
코드는 다음 세 개의 파일로 구성됩니다:
notifiable.rs:"Alert: Something happened!"를 반환하는 기본 구현을 가진notify(&self) -> String메서드를 포함하는 공개(public)Notifiable트레이트를 정의합니다.alerts.rs: 트레이트를 서로 다르게 구현하는 두 개의 공개 구조체를 생성합니다:GenericAlert— 기본 알림을 사용하는 유닛 구조체 (빈 impl 블록 사용)UrgentAlert— 공개message필드(String)를 가지며, 기본 구현을 오버라이드하여"URGENT: {message}"를 반환하는 구조체 (여기서{message}는 저장된 메시지임)
main.rs: 모듈들을 하나로 모으고 두 가지 동작을 모두 보여줍니다. 제공된 입력을 사용하여GenericAlert와UrgentAlert를 생성한 다음, 각각의 알림을 출력합니다.
여기서 핵심은 GenericAlert는 기본 구현으로부터 동작을 그대로 가져오는 반면, UrgentAlert는 자신의 impl 블록에 메서드를 정의함으로써 특수화된 버전을 제공한다는 점입니다.
출력은 다음과 같은 형식이어야 합니다:
Alert: Something happened!
URGENT: {message}예를 들어, 입력이 Server is down!인 경우:
Alert: Something happened!
URGENT: Server is down!긴급 알림에 사용할 메시지 하나를 입력으로 받게 됩니다.
치트 시트
impl 블록에서 직접 구현을 제공하여 기본 트레이트 구현을 재정의할 수 있습니다:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // BEEP BOOP. Unit 42 online.
사용자 정의 동작이 필요하지 않은 타입은 빈 impl 블록을 사용하여 기본 구현을 수락할 수 있으며, 특수 동작이 필요한 타입은 동일한 시그니처로 메서드를 정의하여 특정 메서드를 재정의할 수 있습니다.
직접 해보기
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// 긴급 알림 메시지를 위한 입력을 읽습니다
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: GenericAlert 인스턴스 생성
// TODO: 입력된 메시지로 UrgentAlert 인스턴스 생성
// TODO: GenericAlert의 알림 출력
// TODO: UrgentAlert의 알림 출력
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.