Обобщённые методы
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 25 из 61.
Generic-структура может хранить любой тип, но без методов для взаимодействия с its data она не очень полезна. Чтобы определить методы для generic-структуры, тебе нужен специальный синтаксис в блоке impl.
Главное — объявить параметр generic в самом 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 значением типа integer, строкой или любым другим типом:
let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };
println!("{}", num_wrapper.get()); // 100
println!("{}", text_wrapper.get()); // Rust
Одно и то же определение метода работает для обоих вариантов, потому что обобщённый тип T адаптируется к каждому конкретному типу во время компиляции.
Задание
ЛегкоДавайте расширим ваш generic контейнер с помощью методов! Вы создадите структуру Box (не путать со стандартным Box в Rust), которая может хранить любой тип и предоставляет методы для взаимодействия с её содержимым.
Вы организуете код в двух файлах:
mybox.rs: Define публичную generic структуру под названиемMyBox<T>с private полемcontentsтипаT. Implement методы для этой структуры:- ассоциированную функцию
new, которая Creates новыйMyBoxс given значением - метод
peek, который возвращает reference на contents (с использованием&self) - метод
replace, который принимает новое значение и заменяет current contents (с использованием&mut self)
- ассоциированную функцию
main.rs: Подключите свой модуль и продемонстрируйте работу generic методов с разными типами. Вы создадите контейнеры, заглянете в их contents и замените значения, чтобы показать методы в действии.
Remember ключевой синтаксис для реализации методов в generic структуре: перед MyBox<T> необходимо указать impl<T>, чтобы сообщить Rust, что T является generic параметром для всего блока реализации.
В основном файле продемонстрируйте работу вашего MyBox следующим образом:
- Создайте контейнер с integer (первый ввод, преобразованный в
i32) - Загляните в его contents и выведите значение
- Замените contents новым integer (второй ввод, преобразованный в
i32) - Снова загляните внутрь, чтобы показать обновлённое значение
- Создайте второй контейнер со строкой (третий ввод)
- Загляните в contents строкового контейнера
Ваш вывод должен соответствовать следующему формату:
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Вы получите три ввода: initial integer, replacement integer и строковое значение.
Попробуйте сами
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: Peek at its contents and print: "Integer box contains: {value}"
// TODO: Заменить содержимое на целое число для замены
// TODO: Peek again and print: "After replace: {value}"
// TODO: Создать второй MyBox со строковым значением
// TODO: Peek at the string box and print: "String box contains: {value}"
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust