rust 확장 트레이트 패턴

wangki·2025년 6월 13일
0

Rust

목록 보기
34/54

개요

rust에서 확장 트레이트 구현하기
확장 트레이트를 구현하여 편리한 기능을 제공할 수 있다.
futures 크레이트를 사용하며 select!매크로를 활용할 때 fuse메서드에 대해서 어떻게 사용할 수 있는지 고민하며 해결한 내용을 작성해보겠다.

내용

trait Thing {
    fn do_core(&self);
}

trait ThingExt: Thing {
    fn do_extra(&self) {
        println!("extra");
        self.do_core();
    }
}

impl<T: Thing + ?Sized> ThingExt for T{}

위처럼 확장 트레이트를 구현하게되면 Thing trait를 구현한다면 ThingExt trait에서 제공해주는 기본 메서드를 사용할 수 있다.

struct Test {
    name: String,
}

impl Thing for Test {
    fn do_core(&self) {
        println!("{}", self.name);
    }
}
fn main() {
   let t = Test { name: "홍길동".to_string()};
   t.do_core();
   t.do_extra();
}

Thing trait하나만 구현했지만, ThingExt가 제공하는 메서드 또한 사용할 수 있는것을 확인할 수 있다.

Rust에서 자주사용하는 Future trait의 경우 FutureExt가 구현이 되어있어서 여러가지 확장 메서드를 사용할 수 있다.
futures크레이트의 select매크로를 사용하기위해서는 fuse메서드를 사용해 future객체가 단 한번만 사용이 가능하도록 안전성을 부여해야한다.

// fuse()를 이용한 select! 예시

#[tokio::main]
async fn main() {
   let fut1 = async {
        tokio::time::sleep(Duration::from_secs(2)).await;
        println!("fut1이 종료되었습니다.");
   };

   let fut2 = async {
        tokio::time::sleep(Duration::from_secs(4)).await;
        println!("fut2이 종료되었습니다.");
    };
    
    select! {
        _ = fut1.fuse() => {
            println!("fut1");
        },
        _ = fut2.fuse() => {
            println!("fut2");
        }
    };

    println!("program end ============");
}

결론

    let fut = async {
        println!("안녕하세요?");
    };

    fut.await;
    fut.await;

평소에 사용 시 기본적으로 .await을 하게되면 move가 일어나기 때문에 fuse(0)를 사용하지 않아도 괜찮은 것 같다.

확장 트레이트 패턴은 rust에서 많이 사용되는 패턴이다. 잘 알고 있으면 다른 라이브러리를 분석할 때 유용할 것 같다.

0개의 댓글