Обобщённые методы
Часть раздела Object Oriented Programming путешествия по Rust на Coddy. Урок 25 из 61.
Обобщённая структура может хранить любой тип, но она не очень полезна без методов для взаимодействия с её данными. Чтобы определить методы для обобщённой структуры, вам понадобится специальный синтаксис в блоке impl.
Ключевым моментом является объявление универсального параметра в самом блоке impl:
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
fn get(&self) -> &T {
&self.value
}
}
Обратите внимание на impl<T> перед Wrapper<T>. Это сообщает Rust, что T является параметром обобщённого типа для всего блока реализации. Без этого объявления Rust будет искать конкретный тип с именем T и не сможет его найти.
Метод get возвращает &T — ссылку на любой тип, который содержит обёртка. Это работает независимо от того, является ли T целым числом, строкой или любым другим типом:
let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };
println!("{}", num_wrapper.get()); // 100
println!("{}", text_wrapper.get()); // Rust
Одно и то же определение метода работает для обоих случаев, так как универсальный T адаптируется к каждому конкретному типу во время компиляции.
Задание
ЛегкоДавайте расширим ваш универсальный контейнер с помощью методов! Вы создадите структуру Box (не путайте со стандартным Box в Rust), которая может хранить любой тип и предоставляет методы для взаимодействия с ее содержимым.
Вы организуете свой код в двух файлах:
mybox.rs: Определите публичную универсальную структуру с именемMyBox<T>с приватным полемcontentsтипаT. Реализуйте методы для этой структуры:- Связанную функцию
new, которая создает новыйMyBoxс заданным значением - Метод
peek, который возвращает ссылку на содержимое (используя&self) - Метод
replace, который принимает новое значение и заменяет текущее содержимое (используя&mut self)
- Связанную функцию
main.rs: Подключите свой модуль и продемонстрируйте работу универсальных методов с различными типами. Вы будете создавать боксы, просматривать их содержимое и заменять значения, чтобы показать методы в действии.
Помните ключевой синтаксис для реализации методов в универсальной структуре: вам нужно указать impl<T> перед MyBox<T>, чтобы сообщить Rust, что T является универсальным параметром для всего блока реализации.
В вашем основном файле продемонстрируйте работу MyBox следующим образом:
- Создание бокса с целым числом (первый ввод, преобразованный в
i32) - Просмотр его содержимого и вывод значения
- Замена содержимого новым целым числом (второй ввод, преобразованный в
i32) - Повторный просмотр для отображения обновленного значения
- Создание второго бокса со строкой (третий ввод)
- Просмотр содержимого строкового бокса
Ваш вывод должен соответствовать следующему формату:
Integer box contains: {value}
After replace: {value}
String box contains: {value}Например, при входных данных 10, 25 и Rust:
Integer box contains: 10
After replace: 25
String box contains: RustВы получите три входных значения: начальное целое число, целое число для замены и строковое значение.
Попробуйте сами
mod mybox;
use mybox::MyBox;
fn main() {
// Чтение входных данных
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_int: i32 = input1.trim().parse().expect("Invalid integer");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let replacement_int: i32 = input2.trim().parse().expect("Invalid integer");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let string_value = input3.trim().to_string();
// TODO: Создать MyBox с начальным целым числом
// TODO: Посмотреть содержимое и вывести: "Integer box contains: {value}"
// TODO: Заменить содержимое на новое целое число
// TODO: Снова посмотреть содержимое и вывести: "After replace: {value}"
// TODO: Создать второй MyBox со строковым значением
// TODO: Посмотреть содержимое строкового бокса и вывести: "String box contains: {value}"
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust