Rust 기본 : 상위 특성 (Supertraits)
Rust는 데이터와 행위를 분리하도록 설계되어 있습니다.
데이터는 구조체(struct)와 열거형(enum)으로 정의하고,
행위는 트레잇(trait)을 통해 정의합니다.
(유연성과 안전성 제공)
Supertraits를 사용하는 것은 트레잇간의 관계를 정의하고,
트레잇을 구현할 때 필요한 기본 기능을 강제하는 방법입니다.
(코드의 명확성과 유지보수성을 향상)
결국 Supertraits은 기능 확장의 순서를 잡아줍니다.
B가 A를 supertrait으로 가지면, B를 구현하기 전에 A를 구현해야 합니다.
의존이냐 확장이냐.
- B가 A의 기능에 의존
- A의 기능을 B로 확장
trait A {
fn do_something_a(&self);
}
// B:A - B 트레잇을 사용하려면 A 트레잇을 반드시 구현해야한다.
trait B: A {
fn do_something_b(&self);
}
struct SomeType;
impl A for SomeType {
fn do_something_a(&self) {
println!("Performing something A");
}
}
impl B for SomeType {
fn do_something_b(&self) {
// A의 메소드 호출 가능
self.do_something_a();
println!("Performing something B");
}
}
fn main() {
let my_obj = SomeType;
my_obj.do_something_b();
}
supertrait을 사용하여 trait bound를 단순화 할 수 있습니다.
그러나 복잡한 트레잇 관계는 코드 직관성을 떨어뜨립니다.
범주 | 특징 | 상세 | |
장점 | 중복 감소 | 상위 트레잇에 공통 기능을 정의하여 하위 트레잇 구현의 중복성을 줄인다. | |
구현 강제화 | 특정 트레잇이 다른 트레잇의 기능을 강제로 요구한다. | ||
단점 | 코드 은닉성 | 복잡한 트레잇 구조는 코드 가독성을 떨어뜨린다. | |
유연성 감소 | 구현 강제화가 주는 부작이다. | ||
균형 찾기 | 문서화 | 각 트레잇과 그 관계를 명확히 문서화 한다. | |
단순성 유지 | 트레잇 관계를 간단히 하여 그 역할과 책임을 분명히 한다. |
전체 코드
trait Animal {
fn make_sound(&self);
fn given_name(&self) -> String;
}
trait Playful: Animal {
fn play(&self) {
println!("Animal is sleeping...");
}
}
/* -------------------------------------------------------------------------- */
struct Dog {
name: String,
}
// 메소드 구현
impl Dog {
fn sleep(&self) {
println!("The dog, {}, is sleeping.", self.given_name());
}
}
// 트레잇 구현
impl Animal for Dog {
fn make_sound(&self) {
println!("{} says woof!", self.given_name());
}
fn given_name(&self) -> String {
self.name.clone()
}
}
// 기본 트레잇 덮어쓰기 (trait overwrite)
impl Playful for Dog {
fn play(&self) {
println!("{} loves playing fetch with a ball!", self.given_name());
}
}
/* -------------------------------------------------------------------------- */
// supertrait 관계이므로 Animal 트레잇은 생략할 수 있다. (Playful + Animal)
fn dye_animal_red<T>(object: &T) where T: Playful {
println!("{} animal dye red.", object.given_name());
object.play();
}
/* -------------------------------------------------------------------------- */
fn main() {
let dog = Dog { name: "Buddy".to_string() };
dye_animal_red(&dog);
}
결과
Buddy animal dye red.
Buddy loves playing fetch with a ball!
'개발 > 러스트 (Rust)' 카테고리의 다른 글
Rust 기본 : 특성 객체 (Trait Object) (0) | 2024.09.25 |
---|---|
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 |