C.W.K.
Stream
Lesson 06 of 07 · published

연관 타입

~11 min · traits, associated-types, iterator

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

어떤 trait 은 구현자가 고르는 타입을 가리켜야 해. 연관 타입 은 trait 에 선언되고 각 구현이 못 박는 placeholder 야. canonical 예가 Iterator 야.

Iterator trait

Iteratortype Item;fn next(&mut self) -> Option<Self::Item> 를 선언해. 각 구현자가 Item 이 뭔지 골라 — 카운터는 u32 를, 줄 읽기는 String 을 내놔. 시그니처의 Self::Item 은 그 구현이 고른 게 뭐든 그걸 가리켜.

연관 타입 vs 제네릭 파라미터

Iterator<Item> 을 제네릭으로 상상할 수도 있어. 차이: 제네릭 파라미터는 한 타입이 다른 파라미터로 trait 을 여러 번 구현하게 해; 연관 타입은 구현마다 선택 하나 를 못 박아. 주어진 이터레이터는 원소 타입을 정확히 하나 내놓으니, 연관 타입이 딱 맞아 — 깔끔한 시그니처, 호출 지점에서 모호함 없음.

연관 타입 = impl 마다 선택 하나; 제네릭 파라미터 = 여러 impl. 각 구현자가 합리적 선택이 정확히 하나일 때 (이터레이터의 원소 타입) 연관 타입을 써. 한 타입이 여러 다른 타입에 대해 trait 을 구현할 수 있을 때 제네릭 파라미터를 써 — 여러 소스 타입에 여러 번 구현되는 From<T> 처럼.

Iterator 구현하기

next 를 구현하고 Item 을 고르면, 네 타입이 즉시 이터레이터 도구함 전체를 얻어 — map, filter, sum, collect — 다 네 next 위에 지은 기본 메서드. defaults 레슨의 require-little-provide-lot 설계가 표준 라이브러리에서 제일 많이 쓰이는 trait 에서 본전을 뽑는 거야.

Code

next() 하나, 이터레이터 전체가 공짜·rust
struct Counter { count: u32 }

impl Iterator for Counter {
    type Item = u32;                  // 연관 타입: 이 이터레이터는 u32 를 내놓음
    fn next(&mut self) -> Option<Self::Item> {
        if self.count < 3 {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

fn main() {
    let c = Counter { count: 0 };
    // next() 구현이 map/filter/sum 을 공짜로 풀어줌:
    let total: u32 = c.map(|x| x * 10).sum();
    println!("{total}"); // 60
}

External links

Exercise

u64 값을 내놓는 Fibonacci struct 에 Iterator 를 구현해. 연관 Item 타입을 고르고, next 를 구현하고, 거기에 .take(10).collect::<Vec<_>>() 를 불러. next 만 썼는데 takecollect 는 어디서 왔어?
Hint
takecollectIterator 의 기본 메서드야, 네가 구현한 next 위에 지어진. type Item = u64 를 고른 게 도구함 전체가 u64 를 내놓게 만들어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.