programowanieProgramista Backend

Jak w Rust zrealizowane jest zarządzanie modyfikatorami widoczności (pub, pub(crate), pub(super)) i czym różnią się one od modyfikatorów w innych językach? Jakie problemy mogą wystąpić przy niewłaściwym ustawieniu widoczności elementów modułu?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W Rust modyfikatory widoczności zarządzają dostępem do elementów modułów (struktur, funkcji, stałych itd.). Domyślnie wszystko, co jest zadeklarowane w module, jest prywatne (dostępne tylko w danym module). Istnieją specjalne modyfikatory:

  • pub: czyni element publicznym (widocznym z jakichkolwiek zewnętrznych modułów).
  • pub(crate): widoczność ograniczona do bieżącego crate (pakietu).
  • pub(super): widoczność ograniczona do nadrzędnego modułu.
  • pub(in path): widoczność ograniczona do określonej ścieżki.

Przykład:

mod foo { pub struct Bar { pub x: i32, // pole dostępne wszędzie y: i32, // pole prywatne } pub(crate) fn crate_fn() {} pub(super) fn super_fn() {} fn private_fn() {} }

Główna różnica w porównaniu do np. C++ lub Javy polega na tym, że nie ma oddzielnego poziomu dla protected, a dostępność jest ściśle kontrolowana na poziomie modułów/ścieżek, a nie hierarchii klas.

Pytanie z podstępem.

Pytanie: Jeśli struktura jest zadeklarowana jako pub struct Foo, czy jej prywatne pola będą dostępne w innym module tego samego projektu?

Często odpowiadają: Tak, ponieważ struktura jest publiczna.

Poprawna odpowiedź: Nie, tylko sama struktura (Foo) stanie się widoczna, a jej pola będą dostępne tylko wtedy, gdy również zostaną zadeklarowane z modyfikatorem pub. Pola bez pub pozostają prywatne, nawet jeśli sama struktura jest publiczna.

Przykład:

mod foo { pub struct Bar { pub x: i32, y: i32, } } fn main() { let bar = foo::Bar { x: 1, y: 2 }; // Błąd: pole `y` niedostępne }

Przykłady realnych błędów z powodu braku znajomości szczegółów tematu.


Historia

W dużym projekcie publicznie eksportowano strukturę przez pub, ale pola pozostawiono prywatnymi domyślnie. Inne moduły nie mogły tworzyć instancji struktury bezpośrednio, a jedynym rozwiązaniem było napisanie dodatkowych konstruktorów lub zadeklarowanie odpowiednich pól jako pub. To spowodowało problemy z API aż do ostatecznego zakończenia prac.


Historia

Jeden z deweloperów w bibliotece używał tylko pub(crate) dla funkcji, przypuszczając możliwość ich wywołania z binarnych projektów korzystających z tej biblioteki. Jednak takie funkcje stały się niedostępne w zewnętrznym binarnym crate, co spowodowało problemy z integracją.


Historia

W jednej z wtyczek do serwera API użyto pub(super) dla struktur, ale z czasem pojawiła się potrzeba dostępu do nich z innych modułów; z powodu ustawienia widoczności trzeba było w wielu miejscach znacznie przepisz moduły, aby zapewnić odpowiedni zakres widoczności bez naruszania enkapsulacji.