История вопроса:
В языках вроде C++ или Java модификаторы доступа (public, private, protected) обеспечивают видимость членов класса, но довольно гибко — и часто не предотвращают ошибочное использование API. В Rust, начиная с ранних версий, сделали систему контроля доступа строгой и явно модульной, чтобы ограничить "протекание" внутренних деталей наружу.
Проблема:
Структуру часто нужно частично скрыть от внешнего кода: например, поля приватны, а наружу выставляются только методы. Если не ограничить доступ, можно непреднамеренно испортить инварианты структуры (например, напрямую выставив внутренний Vec). Необдуманная публикация структуры делает API хрупким.
Решение:
В Rust всё приватно по умолчанию. Ключевое слово pub используется для явного экспорта: у структур можно отдельно объявлять саму структуру видимой, а поля — скрытыми. Методы объявляются pub или приватными индивидуально. Кроме того, нестандартные формы вроде pub(crate) или pub(super) позволяют тонко настраивать уровень доступа.
Пример кода:
mod domain { pub struct User { pub name: String, age: u32, // приватное поле } impl User { pub fn new(name: String, age: u32) -> Self { Self { name, age } } pub fn age(&self) -> u32 { self.age } } } use domain::User; fn main() { let u = User::new("Eve".to_string(), 24); println!("{} {}", u.name, u.age()); // u.age — ошибка доступа! поле закрыто вне модуля }
Ключевые особенности:
Можно ли сделать структуру pub, но все её поля оставить приватными? Как тогда создавать её экземпляры за пределами модуля?
Да. Так обычно и делают: структура pub, поля приватные, создание только через публичные конструкторы (например, pub fn new...).
Станет ли поле структуры видимо во внешнем коде при объявлении pub struct Foo?
Нет, по умолчанию каждое поле всё так же приватно — надо явно прописывать pub для поля. pub struct — только делает type видимым.
Работает ли pub для enum так же?
У enum pub распространяется на все варианты, но для ассоциированных данных в вариантах (например, поле внутри Variant(value: T)) всё равно нужно явно указывать pub, если хотите сделать внутренности доступны.
В библиотеке структура была объявлена как pub struct Config, все поля тоже pub — чтобы пользователь "видел" их. В результате любой внешний код мог произвольно менять state, нарушать инварианты, получить panic на ровном месте.
Плюсы:
Минусы:
Структура Config pub, все поля приватные. Для настройки — только через builder-методы, default-конструктор либо setter/getter функции. За пределами модуля нельзя сломать инварианты.
Плюсы:
Минусы: