Rust by Example

13 ジェネリクス

ジェネリクスとは、型と関数の機能をより汎用的に使えるようにするための機能です。これはあらゆる局面でコードの重複を避けるために非常に役立ちますが、多少構文が複雑になります。すなわち、ジェネリック型を使いこなすには、どのようなジェネリック型がきちんと機能するかに細心の注意を払う必要があります。

ジェネリック型の型パラメータにはかぎ括弧(angle brackets)とキャメルケース(camel case)が使われます。: <Aaa, Bbb, ...>ジェネリックな型パラメータはたいていの場合<T>で示されます。Rustの場合、「ジェネリクス」には「1つ以上のジェネリックな型パラメータ<T>を受け付けるもの」という意味もあります。ジェネリックな型パラメータを指定された場合、それは必ずジェネリック型になり、そうでなければ必ず非ジェネリック型、すなわち具象型(concrete)になります。

例として、あらゆる型の引数Tをとるジェネリック関数fooを定義すると:

fn foo<T>(T) { ... }

となります。Tはジェネリックな型パラメータに指定されているので、この場所で(T)のように使用するとジェネリック型として扱われます。これはTという構造体がそれ以前に定義されていても同様です。

では、手を動かしながらジェネリック型の構文を体験していきましょう。

// `A`という具象型 struct A; // `Single`という型を定義する際に`A`を使用しているが、その最初の使用よりも // 先に`<A>`がないため、また、`A`自身も具象型であるため、`Single`は具象型となる。 struct Single(A); // ^ Singleによる`A`の一番最初の使用はここ // ここでは`<T>`が一番初めの`T`の使用よりも先に来ている。よって`SingleGen`はジェネリック型 // となる。なぜならば型パラメータ`T`がジェネリックだからである。`T`はどんな型にもなりえるため、 // 上で定義した`A`を受け取ることもできる。 struct SingleGen<T>(T); fn main() { // `Single`は具象型で、`A`のみを受け取る。 let _s = Single(A); // `_char`という名の変数を生成する。これは`SingleGen<char>` // という型で、値は`SingleGen('a')`となる。ここでは、`SingleGen`には明示的な型パラメータ // が与えられている。 let _char: SingleGen<char> = SingleGen('a'); // `SingleGen`型の変数には明示的に型パラメータを与えなくてもよい。 let _t = SingleGen(A); // 上で定義した`A`を使用 let _i32 = SingleGen(6); // `i32`を使用 let _char = SingleGen('a'); // `char`を使用 }

See also:

構造体