問題
コンテナ型に対してジェネリックな trait には、型指定の要件があります。trait のユーザーは、そのジェネリック型をすべて指定しなければなりません。
以下の例では、Contains trait はジェネリック型 A と B の使用を許可しています。その後、このトレイトは Container 型に対して実装され、A と B に i32 を指定することで、fn difference() で使用できるようにしています。
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)); }