Трейт Drop
Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 56 из 61.
Когда значение выходит из области видимости в Rust, оно автоматически очищается. Но что, если в этот момент нужно выполнить пользовательский код, например записать данные в журнал, освободить ресурс или отправить финальное сообщение? Трейт Drop позволяет точно определить, что произойдёт, когда ваша структура будет уничтожена.
Трейт Drop имеет единственный метод called drop, который принимает &mut self:
struct Connection {
id: u32,
}
impl Drop for Connection {
fn drop(&mut self) {
println!("Connection {} closed.", self.id);
}
}
Ты никогда не вызываешь drop напрямую: Rust вызывает его automatically, когда значение выходит из области видимости:
fn main() {
let conn = Connection { id: 42 };
println!("Using connection...");
} // "Connection 42 closed." печатается здесь автоматически
Результат будет таким:
Using connection...
Connection 42 closed.
Это версия деструктора в Rust. Обычно он используется для задач очистки: закрытия дескрипторов файлов, отключения от серверов или освобождения ресурсов, которыми Rust не может управлять автоматически. Трейт Drop гарантирует выполнение вашего кода очистки, даже если область видимости завершается из-за досрочного возврата.
Задание
ЛегкоДавайте создадим систему управления ресурсами, демонстрирующую автоматическую очистку! Вы создадите структуру FileHandle, которая имитирует открытие и закрытие файлов; когда дескриптор выйдет из области видимости, он автоматически сообщит, что file был закрыт.
Вы организуете код в двух файлах:
file_handle.rs: Определите публичную структуруFileHandleс публичным полемfilename(String). Реализуйте ассоциированную functionnew, которая создаёт FileHandle и выводит сообщение, когда file "opened". Затем реализуйте трейтDrop, чтобы при удалении дескриптора он выводил сообщение о закрытии.main.rs: Подключите свой модуль file_handle и создайте function с именемprocess_file, которая принимает имя file, создаёт FileHandle внутри локальной области видимости и выводит сообщение о processing, пока file "open". Реализация Drop автоматически запустится, когда область видимости закончится. Вызовите эту function с предоставленным input.
При создании FileHandle он должен вывести:
Opening file: {filename}Во время processing (внутри области видимости) выведите:
Processing {filename}...При удалении FileHandle (после завершения области видимости) он должен вывести:
Closing file: {filename}Например, при input data.txt:
Opening file: data.txt
Processing data.txt...
Closing file: data.txtА при input config.json:
Opening file: config.json
Processing config.json...
Closing file: config.jsonВы получите один input: строку с именем file.
ТРЕБУЕМЫЙ ФОРМАТ ВЫВОДА:Попробуйте сами
mod file_handle;
use file_handle::FileHandle;
// TODO: Реализуйте функцию process_file
// Она должна:
// 1. Создать локальную область видимости (используя фигурные скобки {})
// 2. Внутри этой области создать FileHandle с помощью FileHandle::new()
// 3. Вывести сообщение об обработке: "Processing {filename}..."
// 4. Когда область видимости завершится, Drop будет вызван автоматически
fn process_file(filename: &str) {
// TODO: Реализуйте эту функцию
}
fn main() {
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let filename = input.trim();
process_file(filename);
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust