Обобщения

Обобщения (Generics) позволяют абстрагировать типы и функциональность для более общих случаев. Они
чрезвычайно полезны для снижения дублирования кода, однако их синтаксис может быть
сравнительно сложным. А именно, использование обобщений требует особого
внимания при определении того, какими реальными типами в действительности могут заменяться обобщённые.
Наиболее простым и распространённым применением обобщений является обобщение параметров
типа.

Обобщить параметр типа можно используя угловые скобки и верхний верблюжий регистр: <Aaa, Bbb, ...>. "Обобщённые параметры типа" обычно представлены как <T>. В Rust, "обобщённым" также принято называть все, что может принимать один или более обобщённых параметров типа <T>. Любой тип, указанный в качестве параметра обобщённого типа, является обобщённым, а всё остальное является конкретным (не обобщённым).

Например, объявление обобщённой функции foo принимающей аргумент T любого типа:

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

Поскольку T был объявлен как обобщённый тип, посредством <T>, он считается обобщённым когда используется как (arg: T). Это работает даже если T был определён как структура.

Пример ниже демонстрирует синтаксис в действии:

// Конкретный тип `A`.
struct A;

// В определении типа `Single` первому использованию `A` не предшествует `<A>`.
// Поэтому `Single` имеет конкретный тип, и `A` определена выше.
struct Single(A);
//            ^ Здесь `A` в первый раз используется в `Single`.

// В данном примере, `<T>` предшествует первому использованию `T`,
// поэтому `SingleGen` является обобщённым типом.
// Поскольку тип параметра `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`.
}

Смотрите также:

Структуры