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를 사용하는 것이 A나 B를 설명하기 위해 더 이상 필요하지 않다는 것이다:
// 연관된 타입의 사용 없이
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));
}