Перейти к основному содержимому
Модуль 5 · Урок 1 из 29/14 в курсе~12 min
Уроки модуля (1/2)

Дженерики и функции

Обобщенные позволяют писать гибкий код многократного использования, избегая дублирования логики для разных типов данных. Вместо определения нескольких функций или структур для разных типов (например, i32, f64 или String) мы можем использовать параметр универсального типа, обычно обозначаемый буквой T.

Компилятор Rust управляет дженериками с помощью процесса, называемого мономорфизацией: во время компиляции он генерирует копию дженерика для каждого конкретного типа, который фактически используется. Это означает, что накладные расходы на производительность во время выполнения нулевые.


Общие функции

Чтобы определить общую функцию, мы вставляем параметр типа <T> сразу после имени функции и перед списком аргументов:

Rust
fn print_value<T: std::fmt::Debug>(value: T) {
    println!("Value: {:?}", value);
}

В универсальных функциях мы можем использовать универсальный тип T как для типов аргументов, так и для типов возвращаемых значений:

Rust
fn identity<T>(value: T) -> T {
    value
}

Общие структуры

Мы также можем использовать параметры универсального типа внутри структур (struct) для определения гибких полей:

Rust
struct KeyValuePair<K, V> {
    key: K,
    value: V,
}

fn main() {
    let pair = KeyValuePair {
        key: String::from("age"),
        value: 30,
    };
}

В блоке impl для универсальной структуры мы должны объявить параметр типа <T> сразу после ключевого слова impl, чтобы указать, что мы реализуем методы в универсальной структуре:

Rust
struct Container<T> {
    value: T,
}

impl<T> Container<T> {
    fn new(value: T) -> Self {
        Container { value }
    }

    fn value(&self) -> &T {
        &self.value
    }
}

Попробуйте сами

Упражнение 1: Структура Point

Упражнение#rust.m5.l1.e1
Попыток: 0Загрузка…

Определите общую структуру с именем Point<T> с двумя полями: x типа T и y типа T. В основной функции создайте экземпляр переменной point, содержащей Point с целочисленными значениями x = 5 и y = 10, затем напечатайте значение point.x.

Загрузка редактора…
Показать подсказку

Объявите структуру, используя `struct Point<T> { x: T, y: T }`. Создайте его экземпляр в main и используйте `point.x` для его печати.

Решение доступно после 3 попыток

Упражнение 2. Реверсирование кортежа с помощью swap

Упражнение#rust.m5.l1.e2
Попыток: 0Загрузка…

Напишите общую функцию с именем swap<T>, которая принимает кортеж из двух элементов (T, T) и возвращает новый кортеж (T, T) с обратным расположением. В основной функции вызовите функцию с кортежем (1, 2) и распечатайте результат.

Загрузка редактора…
Показать подсказку

Сигнатура функции должна быть `fn swap<T>(pair: (T, T)) -> (T, T)`. Верните перевернутый кортеж с помощью `(pair.1,pair.0)`.

Решение доступно после 3 попыток

Упражнение 3. Структура контейнера

Упражнение#rust.m5.l1.e3
Попыток: 0Загрузка…

Определите универсальную структуру Container<T>, содержащую поле значения типа T. Реализуйте универсальный блок impl, чтобы определить новый метод, который принимает значение типа T и возвращает экземпляр Container<T>.

Загрузка редактора…
Показать подсказку

Используйте `impl<T> Container<T>`для реализации связанного метода`fn new(value: T) -> Self { Container { value } }`.

Решение доступно после 3 попыток