12.7.1 The Problem
그 자신의 포괄 타입에 대해 제네릭 되는 trait은 타입에 대한 선언이 요구된다. - trait 사용자는 반드시 그 자신의 제네릭 타입을 명시해야 한다.
아래의 예제에서, Contains trait이 제네릭 타입 A와 B의 사용을 허용한다. trait은 Container 타입에 구현되고, i32를 A와 B에 명시하여 fn difference()에서 사용될 수 있다.
Containes가 제네릭이라, 우리는 fn difference()을 위한 제네릭 타입 모두의 명시적 상태를 강제해야 한다. 실제로, 우리가 원하는 표현 방식은 A와 B가 입력 값 C에 의해 결정되는 것이다. 당신이 다음 섹션에서 볼 수 있는 연관된 타입들은 정확히 이 기능을 제공한다.
struct Container(i32, i32);
// 컨테이너 내부에 2개의 아이템이 저장되어 있는지 확인하는 trait.
// 또한 첫 번째 또는 마지막 값을 반환한다.
trait Contains<A, B> {
fn contains(&self, &A, &B) -> bool; // `A`와 `B`의 명시적 요구.
fn first(&self) -> i32; // 명시적이지 않은 `A`나 `B`의 요구
fn last(&self) -> i32; // 명시적이지 않은 `A`나 `B`의 요구
}
impl Contains<i32, i32> for Container {
// 저장된 숫자가 같으면 True.
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 }
}
// `C`는 `A`와 `B`를 포함한다. 이 점을 고려하면
// `A`와 `B`를 다시 표현하는 것은 성가시다.
fn difference<A, B, C>(container: &C) -> i32 where
C: Contains<A, B> {
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));
}