Rust 기본 : 특성 (Traits)
러스트는 상속을 지원하지 않습니다.
대신 함수를 공유하고 인터페이스를 제공하기 위해 트레잇(trait)를 사용합니다.
이는 다른 언어의 인터페이스와 유사합니다.
트레잇은 타입의 행동을 추상화하고 규정하는 데 사용합니다.
이를 통해 코드 유연성, 재사용성, 모듈성을 높일 수 있습니다.
트레잇(trait) 선언하기.
1. 공통 특징 트레잇 'Animal' 정의.
동물이 공통적으로 가질 수 있는 특징을 트레잇으로 정의합니다.
trait Animal {
fn make_sound(&self);
fn given_name(&self) -> String;
}
2. 행동 중심 트레잇 'Playful' 정의.
trait Playful {
fn play(&self) {
println!("Animal is sleeping...");
}
}
3. 대상 객체 정의.
struct Cat {
name: String,
}
struct Dog {
name: String,
}
트레잇(trait) 구현하기.
2. Cat 트레잇 구현.
// 선언만 한 트레잇은 반드시 구현해야한다.
impl Animal for Cat {
fn make_sound(&self) {
println!("{} says meow!", self.given_name());
}
fn given_name(&self) -> String {
self.name.clone()
}
}
// 트레잇이 기본 구현을 가지고 있다면 추가 구현 없이 객체에 바로 적용할 수 있다.
impl Playful for Cat {}
3. Dog 트레잇 구현.
// 메소드 구현
impl Dog {
fn sleep(&self) {
println!("The dog, {}, is sleeping.", self.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());
}
}
4. 코드로 확인해보자.
fn main() {
let dog = Dog { name: "Buddy".to_string() };
let cat = Cat { name: "Whiskers".to_string() };
dog.make_sound();
cat.make_sound();
dog.play();
dog.sleep();
cat.play();
}
전체 코드
trait Animal {
fn make_sound(&self);
fn given_name(&self) -> String;
}
trait Playful {
fn play(&self) {
println!("Animal is sleeping...");
}
}
/* -------------------------------------------------------------------------- */
struct Cat {
name: String,
}
// 선언만 한 트레잇은 반드시 구현해야한다.
impl Animal for Cat {
fn make_sound(&self) {
println!("{} says meow!", self.given_name());
}
fn given_name(&self) -> String {
self.name.clone()
}
}
// 트레잇이 기본 구현을 가지고 있다면 추가 구현 없이 객체에 바로 적용할 수 있다.
impl Playful for Cat {}
/* -------------------------------------------------------------------------- */
struct Dog {
name: String,
}
// 메소드 구현
impl Dog {
fn sleep(&self) {
println!("The dog, {}, is sleeping.", self.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());
}
}
/* -------------------------------------------------------------------------- */
fn main() {
let dog = Dog { name: "Buddy".to_string() };
let cat = Cat { name: "Whiskers".to_string() };
dog.make_sound();
cat.make_sound();
dog.play();
dog.sleep();
cat.play();
}
5. 결과
Buddy says woof!
Whiskers says meow!
Buddy loves playing fetch with a ball!
The dog, Buddy, is sleeping.
Animal is sleeping...
참고
트레잇 만들기
- 공통 특성 찾기 : 객체간의 공통 행동이나 속성을 기준으로 만든다.
ex) 움직이다, 먹다, 털색 같은 경우 Animal 트레잇으로 포괄할 수 있다.
- 인터페이스 분리 원칙 (Interface Segregation Principle) : 객체 지향 설계 원칙 SOLID 중 하나.
객체는 자신이 사용하지 않는 메소드에 의존하지 않아야한다.
즉, 구조체 구현에서 trait으로 분리하여 관리한다.
- 행동 기반 설계 : 객체의 상태 보다 행동에 초점을 맞춰 트레잇 정의.
객체가 무엇을 할 수 있는가에 따라 인터페이스 설계. 다형성 통합에 도움.
- 재사용성 증대
재사용 가능한 코드를 만들기 위한 방법인데 공통 특성 찾기와 닮아있다.
ex) 공통 기능 : 시리얼라이징, 비교, 출력 등
- 제네릭 타입의 제약 조건
제네릭 타입이 특정 행동을 보장하며 코드 안정성과 명확성을 향상합니다.
행동 기반 설계
trait Drawable {
fn draw(&self);
}
trait Updateable {
fn update(&mut self);
}
struct Player {
position: (i32, i32),
}
impl Drawable for Player {
fn draw(&self) {
println!("Player at position {:?}", self.position);
}
}
impl Updateable for Player {
fn update(&mut self) {
// Update player's position
self.position.0 += 1;
}
}
'개발 > 러스트 (Rust)' 카테고리의 다른 글
Rust 기본 : 특성 객체 (Trait Object) (0) | 2024.09.25 |
---|---|
Rust 기본 : 상위 특성 (Supertraits) (0) | 2024.09.19 |
Rust 기본 : 특성 제약 (Traits Bounds) (0) | 2024.09.12 |
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 |