ジェネリクス
「ジェネリクス」は、型と機能をより広範なケースに汎用化するトピックです。これは、多くの点でコードの重複を減らすために非常に役立ちますが、かなり複雑な構文を必要とする場合があります。つまり、ジェネリックであることは、ジェネリック型が実際に有効と見なされる型をどのように指定するかについて非常に注意深く対応する必要があります。ジェネリクスの最も単純で一般的な用途は、型パラメータです。
型パラメータは、角括弧と大文字を使ってジェネリックとして指定されます。
通常は <T>
と表されます。Rust では、「ジェネリック」は、1つ以上のジェネリック型パラメータ <T>
を受け取るものを指します。ジェネリック型パラメータとして指定される任意の型はジェネリックであり、それ以外のすべては具体的(非ジェネリック)です。
たとえば、任意の型の引数 T
を受け取る名前 foo
の「汎用関数」を定義すると:
fn foo<T>(arg: T) {... }
T
が <T>
を使ってジェネリック型パラメータとして指定されているため、ここで (arg: T)
として使用される場合、それはジェネリックと見なされます。T
が以前に struct
として定義されていた場合でも、この場合が当てはまります。
この例は、いくつかの構文の使い方を示しています:
// 具体的な型 `A`。
struct A;
// 型 `Single` を定義する際、`A` の最初の使用の前に `<A>` がありません。
// したがって、`Single` は具体的な型であり、`A` は上記のように定義されています。
struct Single(A);
// ^ ここが `Single` が型 `A` を最初に使用する箇所です。
// ここでは、`<T>` が `T` の最初の使用の前にあるため、`SingleGen` はジェネリック型です。
// 型パラメータ `T` はジェネリックであるため、何でもかまいません。
// ここでは、一番上で定義された具体的な型 `A` も含まれます。
struct SingleGen<T>(T);
fn main() {
// `Single` は具体的で、明示的に `A` を受け取ります。
let _s = Single(A);
// 型 `SingleGen<char>` の変数 `_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` を使用します。
}