문제점
컨테이너 타입에 대해 제네릭인 trait는 타입 명시 요구사항을 가집니다 - trait 사용자는 모든 제네릭 타입을 반드시 명시해야 합니다.
아래 예제에서 Contains trait는 제네릭 타입 A와 B의 사용을 허용합니다. 그 후 이 트레이트는 Container 타입에 대해 구현되는데, fn difference()와 함께 사용될 수 있도록 A와 B에 대해 i32를 지정합니다.
Contains가 제네릭이기 때문에, 우리는 fn difference()에 대해 모든 제네릭 타입을 명시적으로 나열해야만 합니다. 실제로는 A와 B가 입력 C에 의해 결정된다는 것을 표현하고 싶습니다. 다음 섹션에서 보게 되겠지만, 연관 타입은 정확히 그런 기능을 제공합니다.
struct Container(i32, i32);
// 컨테이너 안에 2개의 아이템이 저장되어 있는지 확인하는 트레이트입니다.
// 또한 첫 번째 또는 마지막 값을 가져옵니다.
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 {
// 저장된 숫자들이 같으면 참입니다.
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!("컨테이너가 {}와 {}를 포함합니까: {}",
&number_1, &number_2,
container.contains(&number_1, &number_2));
println!("첫 번째 숫자: {}", container.first());
println!("마지막 숫자: {}", container.last());
println!("차이는: {}", difference(&container));
}