Historia pytania:
W językach takich jak C++ czy Java modyfikatory dostępu (public, private, protected) zapewniają widoczność członków klasy, ale raczej elastycznie — i często nie zapobiegają błędnemu używaniu API. W Rust, począwszy od wczesnych wersji, stworzono system kontroli dostępu rygorystyczny i wyraźnie modułowy, aby ograniczyć "przenikanie" wewnętrznych szczegółów na zewnątrz.
Problem:
Strukturę często trzeba częściowo ukryć przed kodem zewnętrznym: na przykład pola są prywatne, a na zewnątrz wystawiane są tylko metody. Jeśli nie ograniczymy dostępu, można niezamierzenie uszkodzić inwarianty struktury (na przykład, bezpośrednio wystawiając wewnętrzny Vec). Nieuważne publikowanie struktury czyni API kruchym.
Rozwiązanie:
W Rust wszystko jest prywatne domyślnie. Słowo kluczowe pub służy do wyraźnego eksportu: struktury można osobno ogłaszać jako widoczne, a pola — jako ukryte. Metody ogłasza się jako pub lub prywatne indywidualnie. Ponadto niestandardowe formy, takie jak pub(crate) lub pub(super), pozwalają na precyzyjne dostosowanie poziomu dostępu.
Przykład kodu:
mod domain { pub struct User { pub name: String, age: u32, // prywatne pole } 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 — błąd dostępu! pole zamknięte poza modułem }
Kluczowe cechy:
Czy można zrobić strukturę pub, ale wszystkie jej pola pozostawić prywatnymi? Jak wtedy tworzyć jej instancje poza modułem?
Tak. Zwykle tak się robi: struktura pub, pola prywatne, tworzenie tylko przez publiczne konstruktory (na przykład, pub fn new...).
Czy pole struktury będzie widoczne w kodzie zewnętrznym przy ogłoszeniu pub struct Foo?
Nie, domyślnie każde pole wciąż jest prywatne — należy wyraźnie zdefiniować pub dla pola. pub struct — tylko czyni typ widocznym.
Czy pub działa dla enum w ten sam sposób?
W przypadku enum pub rozciąga się na wszystkie warianty, ale dla danych powiązanych w wariantach (na przykład, pole wewnątrz Variant(value: T)) również trzeba wyraźnie wskazać pub, jeśli chce się udostępnić wewnętrzności.
W bibliotece struktura została ogłoszona jako pub struct Config, wszystkie pola również publiczne — aby użytkownik "widział" je. W efekcie każdy zewnętrzny kod mógł dowolnie zmieniać stan, naruszając inwarianty, co prowadziło do panic w najmniej oczekiwanym momencie.
Zalety:
Wady:
Struktura Config jest publiczna, wszystkie pola są prywatne. Ustawienia — tylko przez metody budownicze, domyślny konstruktor lub funkcje setter/getter. Poza modułem nie można zepsuć inwariantów.
Zalety:
Wady: