Pola prywatne
Część sekcji Programowanie obiektowe ścieżki Rust w Coddy. Lekcja 10 z 61.
W poprzedniej lekcji wszystko było publiczne: struktura, jej pola i metody. Prawdziwe enkapsulowanie oznacza jednak kontrolowanie, w jaki sposób można uzyskać dostęp do danych. W Rust możesz upublicznić strukturę, zachowując jej pola jako prywatne.
Rozważmy Wallet, który nigdy nie powinien mieć ujemnego salda. Jeśli pole jest publiczne, każdy może ustawić je na dowolną wartość:
// wallet.rs
pub struct Wallet {
balance: f64, // Brak pub = prywatne!
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Wallet { balance: initial }
}
}
Zauważ, że Wallet jest publiczny, ale balance nie ma słowa kluczowego pub. Oznacza to, że kod spoza modułu może utworzyć Wallet za pomocą konstruktora, ale nie może bezpośrednio odczytać ani zmodyfikować pola salda:
// main.rs
mod wallet;
use wallet::Wallet;
fn main() {
let w = Wallet::new(100.0);
// println!("{}", w.balance); // Błąd! Pole jest prywatne
// w.balance = -50.0; // Błąd! Nie można uzyskać dostępu do prywatnego pola
}
To jest podstawa enkapsulacji: struktura kontroluje własne dane. Kod zewnętrzny musi korzystać z udostępnionych przez Ciebie metod, co oznacza, że możesz dodać walidację, rejestrowanie lub dowolną inną logikę. Dane pozostają chronione przed nieprawidłowymi stanami.
W kolejnych lekcjach nauczysz się zapewniać kontrolowany dostęp do tych prywatnych danych za pomocą metod pobierających i ustawiających.
Wyzwanie
ŁatwyZbudujmy system czujnika temperatury, który pokazuje enkapsulację, chroniąc wrażliwe dane wewnątrz modułu.
Utworzysz dwa pliki, aby uporządkować kod:
sensor.rs: Zdefiniuj strukturęTemperatureSensorz dwoma polami:location(String) ireading(f64). Struktura powinna być publiczna, aby można było jej używać z innych plików, ale oba pola pozostaw prywatne: kod zewnętrzny nie powinien mieć możliwości bezpośredniego dostępu do danych czujnika ani ich modyfikowania. Dodaj publiczny konstruktornew, który przyjmuje nazwę lokalizacji i początkowy odczyt temperatury.main.rs: Dołącz moduł czujnika i utwórzTemperatureSensorza pomocą konstruktora. Ponieważ pola są prywatne, nie będzie można ich bezpośrednio wypisać; zamiast tego wypisz komunikat potwierdzający, że czujnik został pomyślnie utworzony.
To wyzwanie skupia się na podstawowej koncepcji prywatnych pól: struktura jest dostępna, ale jej wewnętrzne dane są chronione. Kod zewnętrzny może korzystać z czujnika tylko za pośrednictwem udostępnionych przez Ciebie metod (w tym przypadku jedynie konstruktora).
Wynik powinien mieć dokładnie następujący format:
Sensor created for: {location}Aby uzyskać dostęp do lokalizacji i ją wypisać, funkcja new powinna wypisać ten komunikat przed zwróceniem czujnika, ponieważ samo pole jest prywatne.
Na przykład, jeśli utworzysz czujnik z lokalizacją "Kitchen" i odczytem 22.5, wynikiem będzie:
Sensor created for: KitchenOtrzymasz dwa dane wejściowe: nazwę lokalizacji i początkowy odczyt temperatury.
Spróbuj swoich sił
mod sensor;
use sensor::TemperatureSensor;
fn main() {
// Wczytaj dane wejściowe
let mut location = String::new();
std::io::stdin().read_line(&mut location).expect("Failed to read line");
let location = location.trim().to_string();
let mut reading_str = String::new();
std::io::stdin().read_line(&mut reading_str).expect("Failed to read line");
let reading: f64 = reading_str.trim().parse().expect("Failed to parse reading");
// TODO: Utwórz TemperatureSensor za pomocą konstruktora
// Funkcja new zajmie się wyświetleniem komunikatu potwierdzającego
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Metody i zachowanie
Wprowadzenie do bloków implementacjiParametr selfMetody modyfikująceFunkcje powiązaneWiele bloków implementacjiŁańcuchowe wywoływanie metodPowtórzenie — działania na prostokącie4Projekt: Wirtualne zwierzątko
Definiowanie zwierzątkaKarmienie zwierzątka7Standardowe cechy
Cecha DebugCecha DisplayClone i CopyCechy równościPowtórka – punkt do wydrukowania10Projekt: System dokumentów
Trait DrawKomponent tekstowy2Hermetyzacja i moduły
Podstawy modułówSłowo kluczowe publicPola prywatneGetterySetteryPodsumowanie — bezpieczna skrytka5Typy generyczne
Struktury generyczneMetody generyczneWiele typów generycznychFunkcje generycznePodsumowanie – punkt współrzędnych8Cechy jako ograniczenia
Składnia ograniczeń cechWiele ograniczeńKlauzula whereZwracanie typów z użyciem cechPodsumowanie — generyczna drukarka11Wzorce projektowe w Rust
Wzorzec NewtypeKompozycjaTrait DropFrom i IntoPodsumowanie — atrapowy inteligentny wskaźnik3Zaawansowane typy wyliczeniowe
Typy wyliczeniowe z danymiMetody typów wyliczeniowychDopasowywanie wariantów danychTyp wyliczeniowy Option — powtórzeniePodsumowanie — typ wyliczeniowy Shape6Definiowanie cech
Czym jest cecha?Implementowanie cechImplementacje domyślneNadpisywanie wartości domyślnychCechy z parametramiPowtórzenie — odtwarzacz multimedialnyPoćwicz samodzielnie: Kompilator Rust online