Rust

Rust Trait

Ninestar 2023. 6. 20. 09:49
반응형

타입들이 공통적으로 갖는 동작에 대하여 추상화하도록 해줍니다. 러스트의 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