Historia de la cuestión:
En lenguajes como C++ o Java, los modificadores de acceso (public, private, protected) proporcionan visibilidad a los miembros de una clase, pero de manera bastante flexible — y a menudo no evitan el uso erróneo de la API. En Rust, desde sus primeras versiones, se ha hecho que el sistema de control de acceso sea estricto y claramente modular, con el fin de limitar el "filtrado" de los detalles internos hacia el exterior.
Problema:
A menudo, es necesario ocultar parcialmente una estructura del código externo: por ejemplo, los campos son privados, y solo se exponen los métodos. Si no se limita el acceso, se pueden dañar involuntariamente los invariantes de la estructura (por ejemplo, exponiendo directamente un Vec interno). Publicar sin pensar una estructura hace que la API sea frágil.
Solución:
En Rust, todo es privado por defecto. La palabra clave pub se utiliza para exportar explícitamente: se puede declarar por separado la estructura como visible y los campos como ocultos. Los métodos se declaran públicamente o como privados de forma individual. Además, formas no estándar como pub(crate) o pub(super) permiten ajustar finamente el nivel de acceso.
Ejemplo de código:
mod domain { pub struct User { pub name: String, age: u32, // campo privado } 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 — error de acceso! campo cerrado fuera del módulo }
Características clave:
¿Se puede hacer una estructura pública, pero mantener todos sus campos privados? ¿Cómo se crean instancias de ella fuera del módulo?
Sí. Así es como se suele hacer: estructura pública, campos privados, creación solo a través de constructores públicos (por ejemplo, pub fn new...).
¿Se volverá visible un campo de la estructura al declarar pub struct Foo?
No, por defecto, cada campo sigue siendo privado — hay que declarar explícitamente pub para el campo. pub struct solo hace que el tipo sea visible.
¿Funciona pub para enum de la misma manera?
En enum, pub se aplica a todas las variantes, pero para los datos asociados en las variantes (por ejemplo, un campo dentro de Variant(value: T)) aún hay que especificar explícitamente pub si se desea que las entrañas sean accesibles.
En la biblioteca, la estructura se declaró como pub struct Config, todos los campos también son pub — para que el usuario los "vea". Como resultado, cualquier código externo podía cambiar arbitrariamente el estado, rompiendo invariantes, causando panic de la nada.
Pros:
Contras:
La estructura Config es pública, todos los campos son privados. La configuración — solo a través de métodos de construcción, constructor por defecto o funciones setter/getter. Fuera del módulo no se pueden romper invariantes.
Pros:
Contras: