DataScience
Published 2023. 6. 20. 09:49
Rust Trait Rust
728x90

타입들이 공통적으로 갖는 동작에 대하여 추상화하도록 해줍니다. 러스트의 Trait은 java의 interface, python의 class기능과 유사합니다. trait을 제네릭 파라미터의 타입으로 사용하는 상황에서 trait bound를 통해 서로 다른 구조체에 연관성을 제공할 수 있습니다.

쉽게 말해 일종의 인터페이스로, 정의되지 않은 메서드의 선언들을 가질 수 있습니다.

 

Tait 구조

trait 트레잇명
{
	선언들
}

트레잇은 impl 키워드를 통해서 구조체(클래스)에 구현됩니다.
impl 트레잇명 for 구조체명
{
	구현들
}

 

Trait 구현

정적 메서드만 가지는 간단한 트레잇 소스입니다.

trait Foo{
	fn foo();
}

struct Boom{
}

impl Foo for Boom{
	fn foo(){
		println!("foo");	
	}
}
fn main(){
	Boom::foo();
}
foo

 

동적 메서드에서도 사용 가능합니다.

trait Foo{
	fn foo(&self)->Self;
}

struct Boom{
}

impl Foo for Boom{
	fn foo(&self)->Self{
		println!("foo");	
	}
}
fn main(){
	let obj = Boom();
	let obj2 = obj.foo();
}
foo

 

Dog는 Animal tait 타입으로 구현(impl)했고 추상화된 custom_bark 메서드와 구현된 common_bark메서드 두가지를 갖습니다. custom_bark메서드는 Dog 구현부(impl)에서 강제적으로 정의가 되어야 하지만, common_bark메서드는 정의하지 않고 Animal trait타입으로 구현한 모든 구조체에서 사용할 수 있습니다. 

trait Animal{
    // 선언부만 정의
    fn custom_bark(&self);

    // 선언부,구현부 정의
    fn common_bark(&self) {
        println!("Common Bark");
    }
}

struct Dog{
    Pomeranian : String,
    Poodle : String,
    Dashshund : String,
}

impl Animal for Dog {
    // common_bark 는 Animal 트레잇에서 구현되어 있기 때문에 Dog에서 따로 구현하지 않습니다.

    fn custom_bark(&self){
        println!("Pomeranian Bark : {}", self.Pomeranian);
        println!("Poodle Bark : {}", self.Poodle);
        println!("Dashshund Bark : {}", self.Dashshund);
    }
}

fn main(){
    let dog = Dog{
        Pomeranian : String::from("낑낑"),
        Poodle : String::from("멍멍"),
        Dashshund : String::from("댕댕")
    };

    dog.common_bark();
    dog.custom_bark();
}
Common Bark
Pomeranian Bark : 낑낑
Poodle Bark : 멍멍
Dashshund Bark : 댕댕

 

Trait Bound

트레잇 바운드는 서로 다른 구조체가 동일한 트레잇을 구현하고 있는상황에서 다른 구조체를 파라미터로 가질수 있습니다.

trait Animal{
    // 선언문만 정의
    fn custom_bark(&self);

    // 선언문,구현문 정의
    fn common_bark(&self) {
        println!("Common Bark");
    }
}

struct Dog{
    Pomeranian : String,
    Poodle : String,
    Dashshund : String,
}

struct Cat{
    Ragdoll : String,
    RussianBlue : String,
    Manx : String,
}

impl Animal for Dog {
    // common_bark 는 Animal 트레잇에서 구현되어 있기 때문에 Dog에서 따로 구현하지 않습니다.
    fn custom_bark(&self){
        println!("Dog Bark");
        println!("Pomeranian Bark : {}", self.Pomeranian);
        println!("Poodle Bark : {}", self.Poodle);
        println!("Dashshund Bark : {}", self.Dashshund);
    }
}

impl Animal for Cat {
    // common_bark 는 Animal 트레잇에서 구현되어 있기 때문에 Cat에서 따로 구현하지 않습니다.
    fn custom_bark(&self){
        println!("Cat Bark");
        println!("Ragdoll Bark : {}", self.Ragdoll);
        println!("RussianBlue Bark : {}", self.RussianBlue);
        println!("Manx Bark : {}", self.Manx);
    }
}

// 트레잇 바운드 예시 함수
fn animal_bark<T : Animal>(animal : T){
    animal.custom_bark();
}

fn main(){
    let dog = Dog{
        Pomeranian : String::from("낑낑"),
        Poodle : String::from("멍멍"),
        Dashshund : String::from("댕댕")
    };

    let cat = Cat{
        Ragdoll : String::from("냐옹"),
        RussianBlue : String::from("캬악"),
        Manx : String::from("꾹꾹")
    };

    animal_bark(dog);
    animal_bark(cat);
}
Dog Bark
Pomeranian Bark : 낑낑
Poodle Bark : 멍멍
Dashshund Bark : 댕댕
Cat Bark
Ragdoll Bark : 냐옹
RussianBlue Bark : 캬악
Manx Bark : 꾹꾹

 

리턴 타입

리턴 타입으로 impl Trait 구문을 사용하면 특정 트레이트를 구현하고 있는 타입을 리턴하도록 할 수도 있습니다:

fn double(vector: Vec<i32>) -> impl Iterator<Item = i32> {
    vector.into_iter().map(|x| x * 2)
}

fn main() {
    for num in double(vec![1, 2, 3]) {
        println!("{}", num);
    }
}

'Rust' 카테고리의 다른 글

[Rust] ONNX모델로 detection  (23) 2023.07.02
[Rust-Python] PyO3  (96) 2023.06.30
Rust Generic 데이터 타입  (91) 2023.06.19
Rust testing  (142) 2023.06.15
Rust 파이썬 바인딩  (56) 2023.05.29
profile

DataScience

@Ninestar

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!