ジェネリクス
Generics is the topic of generalizing types and functionalities to broader cases. This is extremely useful for reducing code duplication in many ways, but can call for rather involved syntax. Namely, being generic requires taking great care to specify over which types a generic type is actually considered valid. The simplest and most common use of generics is for type parameters.
A type parameter is specified as generic by the use of angle brackets and upper camel case: <Aaa, Bbb, ...>
. "Generic type parameters" are typically represented as <T>
. In Rust, "generic" also describes anything that accepts one or more generic type parameters <T>
. Any type specified as a generic type parameter is generic, and everything else is concrete (non-generic).
例として、あらゆる型の引数T
をとる ジェネリック関数 foo
を定義すると
fn foo<T>(arg: T) { ... }
Because T
has been specified as a generic type parameter using <T>
, it is considered generic when used here as (arg: T)
. This is the case even if T
has previously been defined as a struct
.
では、手を動かしながらジェネリック型の構文を体験していきましょう。
// `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`を使用。 }