Обобщённые функции
Параметризуйте поведение типом.
«Обобщённые функции» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 4 уроков всего.
Зачем нужны обобщённые функции
Обобщённые функции позволяют написать одну функцию, работающую с разными типами, вместо копирования кода для каждого типа. Rust заменяет тип-заполнитель во время компиляции.
Представьте, что нужно написать одну функцию larger для целых чисел и другую для символов. Обобщения объединяют их в одно определение без затрат во время выполнения.
Параметры типов
Обобщённая функция объявляет параметр типа в угловых скобках после имени. Имя T является общепринятым соглашением, но подойдёт любой идентификатор CamelCase.
Затем параметр можно использовать в аргументах и возвращаемом типе вместо конкретного типа, который выберет вызывающий код.
fn first<T>(pair: (T, T)) -> T {
pair.0
}Простая функция тождественности
Эта программа определяет обобщённую функцию echo, которая возвращает свой аргумент без изменений. Она вызывается один раз с целым числом и один раз со срезом строки.
Компилятор создаёт отдельную конкретную версию для каждого фактически используемого типа.
fn echo<T>(value: T) -> T {
value
}
fn main() {
println!("{}", echo(42));
println!("{}", echo("hi"));
}Мономорфизация
Rust использует мономорфизацию: во время компиляции он создаёт специализированную копию функции для каждого используемого конкретного типа. Упаковка и виртуальная диспетчеризация не требуются.
В результате обобщённый код выполняется так же быстро, как написанный вручную код для конкретного типа.
Обобщения требуют ограничений
Внутри обобщённой функции можно использовать только операции, поддерживаемые всеми возможными типами. К чистому T нельзя прибавлять, сравнивать его или выводить.
Этот код не компилируется, потому что T может не поддерживать сравнение. Далее мы исправим это с помощью ограничения трейта.
fn larger<T>(a: T, b: T) -> T {
if a > b { a } else { b }
}Добавление ограничения трейта
Чтобы сравнивать значения, ограничьте T с помощью PartialOrd. Это ограничение гарантирует, что тип поддерживает оператор >.
Мы также добавим Copy, чтобы возвращать значения без проблем с перемещением для простых типов, таких как целые числа.
fn larger<T: PartialOrd + Copy>(a: T, b: T) -> T {
if a > b { a } else { b }
}Вызов функции с ограничением
Теперь функция работает с любым типом, реализующим оба трейта. Целые числа и числа с плавающей точкой удовлетворяют ограничению PartialOrd + Copy.
Один и тот же исходный код, преобразованный мономорфизацией в две версии, выводит результаты для каждого вызова.
fn larger<T: PartialOrd + Copy>(a: T, b: T) -> T {
if a > b { a } else { b }
}
fn main() {
println!("{}", larger(3, 9));
println!("{}", larger(2.5, 1.0));
}Несколько параметров типов
Функция может объявлять несколько параметров типов. Каждый из них независим, поэтому два аргумента могут иметь разные типы.
Здесь pair принимает любые T и U и возвращает их как кортеж.
fn pair<T, U>(a: T, b: U) -> (T, U) {
(a, b)
}Вывод обобщённых значений
Чтобы вывести обобщённое значение с помощью {}, тип должен реализовывать Display. Мы добавляем это ограничение, чтобы можно было передавать любой тип, поддерживающий вывод.
Функция помечает значение и возвращает его, показывая ограничение, используемое исключительно для форматирования.
use std::fmt::Display;
fn announce<T: Display>(label: &str, value: T) {
println!("{}: {}", label, value);
}
fn main() {
announce("count", 7);
announce("name", "Ada");
}Синтаксис turbofish
Иногда компилятор не может вывести T только из аргументов. Синтаксис turbofish ::<Type> позволяет явно указать его в месте вызова.
Чаще всего он используется с методами вроде parse и collect, когда возвращаемый тип неоднозначен.
fn main() {
let n = "42".parse::<i32>().unwrap();
println!("{}", n + 1);
}Обобщения для ссылок
Параметры обобщённых типов работают и со ссылками. Ограничение через ссылку позволяет не требовать Copy, если нужно только прочитать значения.
Этот вспомогательный код в стиле longest_str заимствует два среза и возвращает один из них, не забирая владение.
fn pick<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
if a > b { a } else { b }
}Быстрая проверка
Проверьте своё понимание обобщённых функций в Rust.
Повторение
Обобщённые функции используют параметры типов в угловых скобках и работают с множеством типов без затрат во время выполнения благодаря мономорфизации.
Операции над обобщённым типом требуют ограничений трейтов, таких как PartialOrd, Copy или Display. Используйте синтаксис turbofish, когда компилятор не может определить тип автоматически.
Часто задаваемые вопросы
Урок «Обобщённые функции» бесплатный?
Да — полный текст урока «Обобщённые функции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 4 уроков всего.
Чему я научусь в уроке «Обобщённые функции»?
Параметризуйте поведение типом. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Learn Rust Coding?
Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Обобщённые функции»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Learn Rust Coding?
Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обобщённые функции
- Обобщённые структуры и перечисления
- Ограничения трейтов
- Предложения where и несколько ограничений