Изучение универсальных шаблонов в Rust: написание гибкого и многократно используемого кода с дженериками типов.
Универсальные шаблоны (дженерики) — это способ написания гибкого и многократно используемого кода, позволяющий указать типы дженериков, которые могут быть заполнены позже при использовании кода. Это похоже на то, как шаблоны работают в C++ или как параметры типа работают в Java и других языках.
С помощью дженериков можно написать код, который сможет работать с любым типом, а не быть специфичным для определенного типа. Это облегчает написание кода, который разработчик может использовать в различных ситуациях без необходимости переписывать код для каждого конкретного типа.
Например, напишите функцию, которая принимает два значения и возвращает их сумму. Без дженериков вам нужно было бы написать отдельную функцию для каждого типа, который вы хотите поддерживать, например:
Дженерики в функциях
Чтобы использовать дженерики в Rust, необходимо сначала объявить параметр универсального типа в определении функции или структуры с помощью `<T>` синтаксиса.
Например, вот простая функция, которая принимает дженерик тип `T` и возвращает его:
Затем эту функцию можно использовать с любым типом, указав параметр типа при вызове функции. Например:
Можно также указать несколько параметров дженериков, разделив их запятой:
Дженерики в структурах
Помимо использования дженериков в определениях функций, их также можно использовать в определениях структур. Например, вот простая реализация связанного списка, использующая дженерики:
В этом примере структура 'Node' имеет общий параметр типа 'T', который представляет тип значения, содержащий узел. Это означает, что вы можете использовать структуру 'Node' с любым типом, например:
Дженерики в trait
Можно также использовать дженерики в определениях trait, чтобы указать типы, для которых разработчик может реализовать характеристику (trait). Например, вот простой trait, которая определяет метод сравнения двух значений:
Этот trait может быть реализован для любого типа `T`, который можно сравнить с помощью метода `cmp`. Например, вы можете реализовать эту характеристику для типа 'i32' следующим образом:
Затем вы можете использовать этот trait с типом 'i32' следующим образом:
Ограничения
Универсальные шаблоны также могут иметь ограничения, которые определяют требования, которым должен соответствовать универсальный тип для использования с функцией или структурой. Например, может потребоваться написать функцию, работающую с любым типом, реализующим атрибут `Add`, который позволяет добавлять два значения одного типа. Вы можете указать это ограничение, используя ключевое слово `where`:
Эта функция принимает два значения типа `T` и возвращает значение типа `T`, и у нее есть ограничение, что `T` должен реализовывать признак `Add`. Это означает, что вы можете использовать эту функцию только с типами, реализующими `Add`, такими как целые числа или числа с плавающей запятой.
Помимо использования ключевого слова `where`, вы также можете использовать границы trait. Привязка trait — это способ указать, что универсальный тип должен реализовывать определенную характеристику (trait). Например:
Вот пример того, как вы можете использовать эту функцию:
Статья на list-site.