Menu
Coddy logo textTech

Трейт Drop

Часть раздела Object Oriented Programming путешествия по Rust на Coddy — урок 56 из 61.

Когда значение выходит из области видимости в Rust, оно автоматически очищается. Но что, если вам нужно выполнить пользовательский код в этот момент — например, логирование, освобождение ресурса или отправку финального сообщения? Трейт Drop позволяет вам точно определить, что происходит, когда ваша структура вот-вот будет уничтожена.

Трейт Drop имеет единственный метод под названием drop, который принимает &mut self:

struct Connection {
    id: u32,
}

impl Drop for Connection {
    fn drop(&mut self) {
        println!("Connection {} closed.", self.id);
    }
}

Вы никогда не вызываете drop напрямую — Rust вызывает его автоматически, когда значение выходит из области видимости:

fn main() {
    let conn = Connection { id: 42 };
    println!("Using connection...");
}  // "Connection 42 closed." выводится здесь автоматически

Результат будет следующим:

Using connection...
Connection 42 closed.

Это версия деструктора в Rust. Он обычно используется для задач очистки: закрытия дескрипторов файлов, отключения от серверов или освобождения ресурсов, которыми Rust не может управлять автоматически. Трейт Drop гарантирует выполнение вашего кода очистки, даже если область видимости завершается из-за раннего возврата.

challenge icon

Задание

Легко

Давайте создадим систему управления ресурсами, которая демонстрирует автоматическую очистку! Вы создадите структуру FileHandle, которая имитирует открытие и закрытие файлов — когда дескриптор выходит из области видимости, он автоматически сообщает о том, что файл был закрыт.

Вы организуете свой код в двух файлах:

  • file_handle.rs: Определите публичную структуру FileHandle с публичным полем filename (String). Реализуйте ассоциированную функцию new, которая создает FileHandle и выводит сообщение, когда файл «открыт». Затем реализуйте типаж Drop, чтобы при удалении дескриптора выводилось сообщение о закрытии.
  • main.rs: Подключите модуль file_handle и создайте функцию process_file, которая принимает имя файла, создает FileHandle внутри локальной области видимости и выводит сообщение об обработке, пока файл «открыт». Реализация Drop автоматически запустится по завершении области видимости. Вызовите эту функцию с предоставленными входными данными.

При создании FileHandle должно выводиться сообщение:

Opening file: {filename}

Во время обработки (внутри области видимости) выведите:

Processing {filename}...

Когда FileHandle удаляется (область видимости заканчивается), должно выводиться сообщение:

Closing file: {filename}

Например, при входных данных data.txt:

Opening file: data.txt
Processing data.txt...
Closing file: data.txt

И при входных данных config.json:

Opening file: config.json
Processing config.json...
Closing file: config.json

Вы получите один входной параметр: строку с именем файла.

Попробуйте сами

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);
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Object Oriented Programming