Gettery i settery — szczegółowo
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 33 z 110.
Gettery i settery stają się potężnymi narzędziami enkapsulacji w połączeniu z polami prywatnymi. Pozwalają udostępnić przejrzysty interfejs publiczny, zachowując pełną kontrolę nad tym, jak dane są odczytywane i modyfikowane.
Często stosuje się wzorzec polegający na połączeniu pola prywatnego z publicznym akcesorem odczytu oraz akcesorem zapisu, który obejmuje walidację:
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15; // Minimum to zero absolutne
} else {
_celsius = value;
}
}
}Settery mogą egzekwować reguły biznesowe, zapewniając, że Twój obiekt nigdy nie znajdzie się w nieprawidłowym stanie.
Możesz również tworzyć gettery obliczane, które wyznaczają wartości na podstawie danych prywatnych:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height; // Obliczane
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}Czasami potrzebujesz dostępu tylko do odczytu. Wystarczy udostępnić getter bez settera:
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt; // Tylko do odczytu
}Ten wzorzec zapewnia zewnętrznemu kodowi dostęp do danych, jednocześnie uniemożliwiając ich modyfikację — prywatne pole w połączeniu z samym getterem zapewnia rzeczywisty dostęp tylko do odczytu.
Wyzwanie
ŁatwyZbudujmy system zarządzania zapasami produktów, który pokaże możliwości getterów i setterów w kontrolowaniu dostępu do danych. Utworzysz klasę, która chroni swoje wewnętrzne dane, udostępniając jednocześnie właściwości obliczane i walidację.
Podzielisz kod na dwa pliki:
product.dart: Zdefiniuj klasęProduct, która zarządza zapasami z użyciem prawidłowej enkapsulacji. Produkt powinien mieć:- Publiczne
String name - Prywatne
double _price - Prywatne
int _quantity - Konstruktor przyjmujący wszystkie trzy wartości
- Getter
price, który zwraca prywatną cenę - Setter
price, który akceptuje tylko wartości większe niż0(ignoruj nieprawidłowe wartości) - Getter
quantity, który zwraca prywatną ilość - Setter
quantity, który akceptuje tylko wartości równe0lub większe (ignoruj wartości ujemne) - Obliczany getter
totalValue, który zwraca_price * _quantity - Obliczany getter
isInStock, który zwracatrue, jeśli ilość jest większa niż0 - Tylko do odczytu getter
sku, który generuje prosty SKU, zwracając pierwsze 3 znaki nazwy zapisane wielkimi literami, a następnie ilość (np.LAP25dla "Laptop" z ilością 25) - Metoda
displayProduct(), która wyświetla szczegóły produktu
- Publiczne
main.dart: Zaimportuj klasę produktu i pokaż, jak gettery i settery kontrolują dostęp:- Utwórz produkt o nazwie
'Laptop', cenie999.99i ilości25 - Wywołaj
displayProduct() - Wypisz
In stock: [isInStock] - Wypisz
SKU: [sku] - Spróbuj ustawić cenę na
-50.0(powinna zostać zignorowana) - Ustaw cenę na
899.99(prawidłowa zmiana) - Spróbuj ustawić ilość na
-10(powinna zostać zignorowana) - Ustaw ilość na
0(prawidłowa zmiana) - Wywołaj
displayProduct() - Wypisz
In stock: [isInStock] - Wypisz
SKU: [sku]
- Utwórz produkt o nazwie
Metoda displayProduct() powinna wypisywać dane w tym formacie:
--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]Oczekiwany wynik:
--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0Spróbuj swoich sił
import 'product.dart';
void main() {
// TODO: Utwórz produkt o nazwie 'Laptop', cenie 999.99 i ilości 25
// TODO: Wywołaj displayProduct()
// TODO: Wypisz "In stock: [isInStock]"
// TODO: Wypisz "SKU: [sku]"
// TODO: Spróbuj ustawić cenę na -50.0 (powinno zostać zignorowane)
// TODO: Ustaw cenę na 899.99 (poprawna zmiana)
// TODO: Spróbuj ustawić ilość na -10 (powinno zostać zignorowane)
// TODO: Ustaw ilość na 0 (poprawna zmiana)
// TODO: Wywołaj displayProduct()
// TODO: Wypisz "In stock: [isInStock]"
// TODO: Wypisz "SKU: [sku]"
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online