0Pricing
Learn Rust Coding · Урок

Написание обобщённого кода на Rust

Научитесь писать функции и структуры данных, работающие с несколькими типами, повышая повторное использование кода без ущерба для безопасности типов.

«Написание обобщённого кода на Rust» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 1 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 3 уроков всего.

Зачем писать обобщённый код?

Представьте, что Вам нужна функция, находящая наибольший элемент в списке. Что, если она должна работать с числами, затем с символами, а затем с пользовательскими объектами?

Без обобщений пришлось бы писать отдельную функцию для каждого типа, что привело бы к большому количеству повторяющегося кода. Здесь и пригодятся обобщения!

Знакомство с обобщениями

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

Представьте их как чертёж, который можно адаптировать под разные материалы.

Ваша первая обобщённая функция

Чтобы сделать функцию обобщённой, объявите параметры типов в угловых скобках <> после имени функции. Обычно параметр типа называют T (от Type — «тип»).

Теперь эта функция print_anything может выводить значения любого типа!

fn print_anything<T>(item: T) {
    println!("The item is: {}", item);
}

pub fn main() {
    print_anything(5);
    print_anything("hello");
    print_anything(true);
}

Параметры типов

<T> в fn print_anything<T>(item: T) означает, что T — это обозначение типа. Когда Вы вызываете функцию с типом i32, T становится равным i32.

  • Параметры типов: обобщённые типы обычно обозначают заглавными буквами, например T, U, V.
  • Гибкость: компилятор определяет конкретный тип во время компиляции.

Добавление поведения: ограничения трейтов

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

Для указания этих требований добавляют ограничения трейтов. Здесь T: PartialOrd + Copy означает, что тип T должен реализовывать трейты PartialOrd (частичный порядок для сравнения) и Copy.

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

pub fn main() {
    let number_list = vec![34, 50, 25, 100, 65];
    println!("Largest number: {}", largest(&number_list));

    let char_list = vec!['y', 'm', 'a', 'q'];
    println!("Largest char: {}", largest(&char_list));
}

Синтаксис нескольких ограничений трейтов

Вы можете потребовать от обобщённого типа реализации нескольких трейтов, используя синтаксис с +, например T: TraitA + TraitB.

Для сложных ограничений можно также использовать предложение where после сигнатуры функции — это может сделать сигнатуру понятнее:

fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { /* ... */ }

Обобщённые структуры

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

Структура Point<T> может хранить координаты любого типа T (например, i32 или f64).

struct Point<T> {
    x: T,
    y: T,
}

pub fn main() {
    let integer_point = Point {
        x: 5,
        y: 10
    };
    let float_point = Point {
        x: 1.0,
        y: 4.0
    };

    println!("Int Point: ({}, {})", 
             integer_point.x, integer_point.y);
    println!("Float Point: ({}, {})", 
             float_point.x, float_point.y);
}

Реализация методов для обобщённых структур

При реализации методов для обобщённой структуры нужно указать параметры обобщённых типов после impl.

Вы также можете добавить ограничения трейтов для методов, если конкретному методу требуется определённое поведение его обобщённых типов.

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

pub fn main() {
    let p = Point {
        x: 5,
        y: 10
    };
    println!("p.x = {}", p.x());
}

Обобщения и производительность

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

Rust достигает этого с помощью мономорфизации: во время компиляции компилятор создаёт специализированные версии обобщённого кода для каждого конкретного типа, с которым он используется. Поэтому largest<i32> и largest<char> становятся двумя разными оптимизированными функциями.

Проверьте свои знания

Какие из следующих утверждений об обобщениях Rust являются TRUE?

Итоги: сила обобщений

На этом уроке Вы изучили основы написания обобщённого кода в Rust:

  • Что это такое: способ писать гибкий и повторно используемый код.
  • Обобщённые функции: использование <T> для параметров типов.
  • Ограничения трейтов: указание требуемого поведения с помощью T: Trait.
  • Обобщённые структуры: создание структур данных, работающих с обобщёнными типами.
  • Отсутствие дополнительных затрат: обобщения Rust компилируются в специализированный код, не снижая производительность во время выполнения.

Обобщения — основа идиоматичного Rust, позволяющая создавать мощные абстракции с гарантией безопасности типов!

Часто задаваемые вопросы

Урок «Написание обобщённого кода на Rust» бесплатный?

Да — полный текст урока «Написание обобщённого кода на Rust» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 3 уроков всего.

Чему я научусь в уроке «Написание обобщённого кода на Rust»?

Научитесь писать функции и структуры данных, работающие с несколькими типами, повышая повторное использование кода без ущерба для безопасности типов. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Learn Rust Coding?

Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 3.

Сколько времени занимает урок «Написание обобщённого кода на Rust»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Learn Rust Coding?

Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Написание обобщённого кода на Rust
  2. Определение и реализация трейтов
  3. Продвинутое использование трейтов: связанные типы
← Назад к Learn Rust Coding