境界
ジェネリックプログラミングをしていると、型パラメータが特定の機能を持っていることを規定するため、トレイトに境界を設ける必要があることがよくあります。例えば、以下の例では、引数のDisplay
トレイトを用いて出力を行うため、T
がDisplay
を持っていることを規定しています。つまり、「T
はDisplay
を実装 していなくてはならない 」という意味です。
// `Display`トレイトを実装している`T`を引数として取ります。
// `printer`という関数を定義。
fn printer<T: Display>(t: T) {
println!("{}", t);
}
境界は、ジェネリクスを全ての型ではなく、一定条件を満たす型に対してのみ適用するためにあります。つまり
struct S<T: Display>(T);
// エラー!`Vec<T>`は`Display`を実装していないため、この特殊化
// は失敗します。
let s = S(vec![1]);
境界のもう一つの効果は、ジェネリック型のインスタンスが、境界条件となるトレイトのメソッドにアクセスすることができるようになる点です。以下がその例です。
付け加えておくと、where
句を用いて境界を適用することもできます。場合によってはこちらの記法を使用したほうが読みやすくなる場合もあります。