Программирование RustRust CoreRust-разработчик серверных приложений

У публичной структуры одно поле объявлено без pub: что именно сможет и чего не сможет сделать код из другог...

У публичной структуры одно поле объявлено без pub: что именно сможет и чего не сможет сделать код из другого crate?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Код из другого crate сможет использовать имя структуры, но не сможет напрямую читать, изменять или задавать приватное поле. Значение такой структуры можно получить через публичную функцию или метод, а доступ к скрытому состоянию должен предоставляться через публичный API.

Исторический контекст

Приватность в Rust по умолчанию решает задачу инкапсуляции: внутреннее представление типа не становится частью внешнего контракта без явного разрешения. Это позволяет менять поля и внутреннюю реализацию, сохраняя совместимый публичный интерфейс.

Такой подход также уменьшает число мест, где код может нарушить инварианты типа. Создатель структуры сам определяет, какие операции допустимы извне.

Постановка проблемы

pub у структуры и pub у её полей — независимые свойства. Если сделать публичным только сам тип, внешний код сможет объявлять переменные этого типа, передавать их в функции и возвращать их, но не сможет обратиться к скрытому полю.

Неверное предположение, что публичный тип полностью доступен, приводит к ошибкам компиляции при создании значения через литерал структуры, чтении поля, присваивании ему или деструктуризации.

Подробное решение

Приватное поле доступно в модуле, где объявлена структура, и его дочерних модулях согласно правилам видимости Rust. Код из другого crate находится за границей этого модуля и не получает доступ к полю автоматически.

Минимальный пример:

pub struct Account { pub name: String, balance: u64, } impl Account { pub fn new(name: String, balance: u64) -> Self { Self { name, balance } } pub fn balance(&self) -> u64 { self.balance } }

Внешний код может обратиться к name и вызвать balance(), но не может напрямую использовать account.balance. Он также не сможет создать Account через литерал структуры, потому что для такого создания нужно указать значение приватного поля.

Публичный метод может безопасно изменять приватное поле и проверять инварианты. Например, метод пополнения баланса может отклонять недопустимое значение; прямое публичное поле лишило бы тип такого контроля.

Ситуация из практики

Библиотека предоставляет тип конфигурации соединения. Вариант с публичными полями прост для пользователя, но позволяет создать некорректную комбинацию параметров и связывает библиотеку с конкретным представлением данных.

Вариант с полностью приватными полями и публичными конструкторами лучше защищает инварианты, но требует написать методы чтения и изменения состояния. Выбранное решение — публичная структура с приватными полями и проверяющим конструктором: пользователь получает удобный тип, а библиотека сохраняет контроль над допустимыми значениями.

Что кандидаты часто упускают

  1. Можно ли внешнему коду деструктурировать публичную структуру с приватным полем?

Нет. Деструктуризация требует доступа к каждому явно извлекаемому полю, поэтому приватное поле остаётся недоступным. Внешний код должен использовать публичные методы или другой предусмотренный API.

  1. Разрешает ли публичный метод доступ к приватному полю?

Да, метод проверяет права доступа в месте своего определения. Внутри реализации метода поле доступно, а вызывающий код получает только результат или ссылку, которую метод явно возвращает. Если метод возвращает изменяемую ссылку на поле, он может предоставить контролируемый косвенный доступ к его содержимому.

  1. Становятся ли приватные поля доступными из-за Debug или другого публичного трейта форматирования?

Нет. Реализация Debug может вывести содержимое поля в текст, но это не меняет правил доступа к нему: внешний код по-прежнему не может обратиться к полю по имени или деструктурировать его. Формат вывода при этом становится частью наблюдаемого поведения реализации, поэтому чувствительные данные не следует бездумно включать в отладочное представление.