Rust 기본 : 특성 객체 (Trait Object)
러스트에서 특성 객체(trait object)는 특정 트레잇을 구현한 모든 타입의 인스턴스를 동적으로 처리할 수 있습니다. 이런 동적 처리(dynamic dispatch)는 런타임에 어떤 타입으로 결정된 메서드가 호출될지 결정하므로 해당 트레잇을 지원하는 다양한 타입(struct, enum)을 동일한 방식으로 처리할 때 사용합니다.
객체 생성 함수
- 정적 처리(static dispatch)
: create_hynix_memory() -> impl Compatible
특성 객체를 impl Compatible 방법으로 트레잇 리턴할 수 있습니다.
컴파일 시간에 호출 함수를 결정하기 때문에 런타임 성능이 좋습니다.
- 동적 처리(dynamic dispatch)
: create_compatible_memory(is_samsung: bool) -> Box<dyn Compatible>
특성 객체를 Box<dyn Compatible> 방식으로 감싸서 실행 시간에 리턴할 객체를 결정합니다.
실행 시간에 호출 함수를 결정하기 때문에 런타임 성능을 떨어지지만 코드 유연성은 올라갑니다.
// return static dispatch
fn create_hynix_memory() -> impl Compatible {
HynixMemory { size: 16, speed: 2400 }
}
// return dynamic dispatch
fn create_compatible_memory(is_samsung: bool) -> Box<dyn Compatible> {
if is_samsung {
Box::new(SamsungMemory { size: 24, speed: 2400 })
}
else {
Box::new(HynixMemory { size: 16, speed: 2400 })
}
}
런타임 사용이 많은 로직은 정적 처리로 구현하고 나머지는 동적 처리로 코드 유연성을 높일 수 있습니다.
특성 객체 object를 함수 파라미터로 사용
- 정적 처리 파라미터 : trait bound를 파라미터를 받는다. ex) &impl Trait
- 동적 처리 파라미터 : trait object를 파라미터로 받는다. ex) &dyn Trait
// static parameter dispatch: &impl Trait
fn check_memory(object: &impl Compatible, other_speed: u32) -> bool {
object.is_compatible(other_speed)
}
// dynamic parameter dispatch: &dyn trait
fn check_memory_dyn(object: &dyn Compatible, other_speed: u32) -> bool {
object.is_compatible(other_speed)
}
전체 코드
// 호환(Compatible)과 업그레이드(Upgrade)는 의존 관계이다.
// 업그레이드 트레잇은 호환 트레잇에 의존한다. (종속)
trait Compatible {
//fn is_compatible(&self, other: &Self) -> bool;
fn is_compatible(&self, speed: u32) -> bool;
}
trait Upgradeable: Compatible {
fn upgrade(&mut self);
}
/* -------------------------------------------------------------------------- */
struct HynixMemory {
size: u32, // 메모리 크기 (예: GB 단위)
speed: u32, // 메모리 속도 (예: MHz 단위)
}
impl Compatible for HynixMemory {
fn is_compatible(&self, otherSpeed: u32) -> bool {
self.speed == otherSpeed
}
}
impl Upgradeable for HynixMemory {
fn upgrade(&mut self) {
if self.size < 32 {
println!("Upgrading from {}GB to 32GB.", self.size);
self.size = 32; // 예를 들어 최대 크기로 업그레이드
} else {
println!("Maximum upgrade size reached.");
}
}
}
/* -------------------------------------------------------------------------- */
struct SamsungMemory {
size: u32, // 메모리 크기 (예: GB 단위)
speed: u32, // 메모리 속도 (예: MHz 단위)
}
impl Compatible for SamsungMemory {
fn is_compatible(&self, otherSpeed: u32) -> bool {
self.speed == otherSpeed
}
}
impl Upgradeable for SamsungMemory {
fn upgrade(&mut self) {
if self.size < 32 {
println!("Upgrading from {}GB to 32GB.", self.size);
self.size = 32; // 예를 들어 최대 크기로 업그레이드
} else {
println!("Maximum upgrade size reached.");
}
}
}
/* -------------------------------------------------------------------------- */
// static parameter: object
fn check_memory<T: Compatible>(object: &T, other_speed: u32) -> bool {
object.is_compatible(other_speed)
}
// dynamic parameter: object
fn check_memory_dyn(object: &dyn Compatible, other_speed: u32) -> bool {
object.is_compatible(other_speed)
}
/* -------------------------------------------------------------------------- */
// return static dispatch
fn create_hynix_memory() -> impl Compatible {
HynixMemory { size: 16, speed: 2400 }
}
// return dynamic dispatch
fn create_compatible_memory(is_samsung: bool) -> Box<dyn Compatible> {
if is_samsung {
Box::new(SamsungMemory { size: 24, speed: 2400 })
}
else {
Box::new(HynixMemory { size: 16, speed: 2400 })
}
}
/* -------------------------------------------------------------------------- */
fn main() {
let hynix_memory = HynixMemory { size: 16, speed: 2400 };
let compatible_memory = create_compatible_memory(true);
check_memory(&hynix_memory, 16);
check_memory_dyn(compatible_memory.as_ref(), 32);
}
enum을 사용한 trait object.
trait Animal {
fn speak(&self) -> String;
}
enum Creature {
Dog,
Cat,
}
impl Animal for Creature {
fn speak(&self) -> String {
match self {
Creature::Dog => "Woof!".to_string(),
Creature::Cat => "Meow!".to_string(),
}
}
}
fn main() {
let my_pet: Box<dyn Animal> = Box::new(Creature::Dog);
println!("{}", my_pet.speak());
}
'개발 > 러스트 (Rust)' 카테고리의 다른 글
Rust 기본 : 상위 특성 (Supertraits) (0) | 2024.09.19 |
---|---|
Rust 기본 : 특성 제약 (Traits Bounds) (0) | 2024.09.12 |
Rust 기본 : 특성 (Traits) (0) | 2024.09.07 |
Rust 기본 : 일반화 (Generics) (0) | 2024.09.03 |
Rust 기본 : 벡터 (Vector) (0) | 2024.08.26 |
Rust 기본 : 결과 열거형 (Result enum) (0) | 2024.08.21 |
Rust 기본, 옵션 열거형 (Option enum) (0) | 2024.08.17 |
Rust 기본, 패턴 매칭 표현식 (Match expression) (0) | 2024.08.13 |