12.7.2 Associated types

"연관된 타입들"의 사용이 향상시키는 코드의 전체 가독성은 지역적 내부 타입들을 output 타입인 trait으로 이동시킴으로서 가능하다. trait을 위한 문법 정의는 다음과 같다:

// `A`와 `b`는 `type` 키워드를 통해 정의된다. 
// (주의: 이 문맥에서 `type`은 별칭으로 사용될 때의 `type`과는 다르다.
trait Contains {
    type A;
    type B;

    // 이 새로운 type들을 제네릭하게 참조하도록 구문을 업데이트.
    fn contains(&self, &Self::A, &Self::B) -> bool;
}

이들 함수에서 주목할 점은 trait``Contains를 사용하는 것이 AB를 설명하기 위해 더 이상 필요하지 않다는 것이다:

// 연관된 타입의 사용 없이
fn difference<A, B, C>(container: &C) -> i32 where
    C: Contains<A, B> { ... }

// 연관된 타입을 사용 하여
fn difference<C: Contains>(container: &C) -> i32 { ... }

이전 섹션의 예제를 연관 타입으로 재작성해보자:

struct Container(i32, i32);

// 컨테이너 내부에 2개의 아이템이 저장되어 있는지 확인하는 trait. 
// 또한 첫 번째 또는 마지막 값을 반환한다.
trait Contains {
    // 메소드가 사용할 수 있는 제네릭 타입을 정의한다.
    type A;
    type B;

    fn contains(&self, &Self::A, &Self::B) -> bool;
    fn first(&self) -> i32;
    fn last(&self) -> i32;
}

impl Contains for Container {
    // `A`와 `B`의 타입을 지정한다. 만약 `input` 타입이 `Container(i32,i32)`이면
    // `output` 타입은 `i32`와 `i32`로 결정된다.
    type A = i32;
    type B = i32;

    // `&Self::A`와 `&Self::B` 역시 유효하다.
    fn contains(&self, number_1: &i32, number_2: &i32) -> bool {
        (&self.0 == number_1) && (&self.1 == number_2)
    }
    // 첫 번째 숫자를 가져온다.
    fn first(&self) -> i32 { self.0 }

    // 마지막 숫자를 가져온다.
    fn last(&self) -> i32 { self.1 }
}

fn difference<C: Contains>(container: &C) -> i32 {
    container.last() - container.first()
}

fn main() {
    let number_1 = 3;
    let number_2 = 10;

    let container = Container(number_1, number_2);

    println!("Does container contain {} and {}: {}",
        &number_1, &number_2,
        container.contains(&number_1, &number_2));
    println!("First number: {}", container.first());
    println!("Last number: {}", container.last());

    println!("The difference is: {}", difference(&container));
}

results matching ""

    No results matching ""