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)); }