Уроки модуля (1/2)
Дженерики и функции
Обобщенные позволяют писать гибкий код многократного использования, избегая дублирования логики для разных типов данных. Вместо определения нескольких функций или структур для разных типов (например, i32, f64 или String) мы можем использовать параметр универсального типа, обычно обозначаемый буквой T.
Компилятор Rust управляет дженериками с помощью процесса, называемого мономорфизацией: во время компиляции он генерирует копию дженерика для каждого конкретного типа, который фактически используется. Это означает, что накладные расходы на производительность во время выполнения нулевые.
Общие функции
Чтобы определить общую функцию, мы вставляем параметр типа <T> сразу после имени функции и перед списком аргументов:
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Value: {:?}", value);
}В универсальных функциях мы можем использовать универсальный тип T как для типов аргументов, так и для типов возвращаемых значений:
fn identity<T>(value: T) -> T {
value
}Общие структуры
Мы также можем использовать параметры универсального типа внутри структур (struct) для определения гибких полей:
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("age"),
value: 30,
};
}В блоке impl для универсальной структуры мы должны объявить параметр типа <T> сразу после ключевого слова impl, чтобы указать, что мы реализуем методы в универсальной структуре:
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}Попробуйте сами
Упражнение 1: Структура Point
Определите общую структуру с именем 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
Напишите общую функцию с именем swap<T>, которая принимает кортеж из двух элементов (T, T) и возвращает новый кортеж (T, T) с обратным расположением. В основной функции вызовите функцию с кортежем (1, 2) и распечатайте результат.
Показать подсказку
Сигнатура функции должна быть `fn swap<T>(pair: (T, T)) -> (T, T)`. Верните перевернутый кортеж с помощью `(pair.1,pair.0)`.
Решение доступно после 3 попыток
Упражнение 3. Структура контейнера
Определите универсальную структуру Container<T>, содержащую поле значения типа T. Реализуйте универсальный блок impl, чтобы определить новый метод, который принимает значение типа T и возвращает экземпляр Container<T>.
Показать подсказку
Используйте `impl<T> Container<T>`для реализации связанного метода`fn new(value: T) -> Self { Container { value } }`.
Решение доступно после 3 попыток