Klasy zapieczętowane (Dart 3)
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 85 z 110.
Dart 3 wprowadził klasy zapieczętowane, które ograniczają, jakie klasy mogą je rozszerzać lub implementować. Gdy oznaczysz klasę jako sealed, tylko klasy z tego samego pliku mogą być jej bezpośrednimi podtypami. Tworzy to zamknięty zbiór znanych podtypów.
sealed class Result {}
class Success extends Result {
final String data;
Success(this.data);
}
class Failure extends Result {
final String error;
Failure(this.error);
}Siła klas zapieczętowanych wynika ze sprawdzania wyczerpującego. Gdy używasz instrukcji switch dla typu zapieczętowanego, kompilator zna wszystkie możliwe podtypy i upewnia się, że obsługujesz każdy z nich:
String handleResult(Result result) {
return switch (result) {
Success(data: var d) => 'Got: $d',
Failure(error: var e) => 'Error: $e',
};
// Nie potrzeba default — kompilator wie, że uwzględniono wszystkie przypadki!
}
void main() {
var success = Success('Hello');
var failure = Failure('Not found');
print(handleResult(success)); // Got: Hello
print(handleResult(failure)); // Error: Not found
}Jeśli dodasz nowy podtyp do klasy zapieczętowanej, kompilator oznaczy każdą instrukcję switch, która go nie obsługuje. Dzięki temu klasy zapieczętowane idealnie nadają się do modelowania stanów, wyników lub dowolnego scenariusza, w którym masz stały zestaw wariantów. W przeciwieństwie do klas abstrakcyjnych klasy zapieczętowane gwarantują, że żaden zewnętrzny kod nie może dodać nieoczekiwanych podtypów.
Wyzwanie
ŁatwyZbudujmy obsługę żądań sieciowych przy użyciu klas zapieczętowanych! Utworzysz bezpieczny typowo system, który modeluje różne stany odpowiedzi sieciowej, zapewniając prawidłową obsługę każdego możliwego wyniku.
Podzielisz kod na dwa pliki:
response.dart: Utwórz hierarchię klas zapieczętowanych, która reprezentuje wszystkie możliwe stany odpowiedzi sieciowej:- Klasę zapieczętowaną o nazwie
NetworkResponse, która służy jako klasa bazowa dla wszystkich typów odpowiedzi - Klasę
Loading, która rozszerzaNetworkResponseo poleString message(np. "Fetching data...") - Klasę
Success, która rozszerzaNetworkResponseo poleString dataoraz poleint statusCode - Klasę
Error, która rozszerzaNetworkResponseo poleString errorMessageoraz poleint errorCode
- Klasę zapieczętowaną o nazwie
main.dart: Zaimportuj plik z odpowiedzią i utwórz funkcję, która obsługuje wszystkie typy odpowiedzi za pomocą wyrażenia switch:- Utwórz funkcję
handleResponse(NetworkResponse response), która zwracaString - Użyj wyrażenia switch z dopasowywaniem do wzorca, aby obsłużyć każdy przypadek:
- Dla
Loading: zwróćStatus: [message] - Dla
Success: zwróćSuccess ([statusCode]): [data] - Dla
Error: zwróćError ([errorCode]): [errorMessage]
- Dla
- Utwórz trzy instancje odpowiedzi i wypisz wynik obsługi każdej z nich:
Loadingz komunikatemPlease wait...Successz danymiUser profile loadedi kodem stanu200Errorz komunikatem błęduNot foundi kodem błędu404
- Utwórz funkcję
Zaletą klas zapieczętowanych jest to, że kompilator dopilnuje obsłużenia każdego możliwego typu odpowiedzi — nie jest potrzebny przypadek domyślny!
Oczekiwany wynik:
Status: Please wait...
Success (200): User profile loaded
Error (404): Not foundSpróbuj swoich sił
import 'response.dart';
// TODO: Utwórz funkcję handleResponse(NetworkResponse response)
// która zwraca String
// Użyj wyrażenia switch z dopasowaniem wzorców, aby obsłużyć każdy przypadek:
// - Dla Loading: zwróć "Status: [message]"
// - Dla Success: zwróć "Success ([statusCode]): [data]"
// - Dla Error: zwróć "Error ([errorCode]): [errorMessage]"
void main() {
// TODO: Utwórz instancję Loading z komunikatem "Please wait..."
// TODO: Utwórz instancję Success z danymi "User profile loaded" i kodem statusu 200
// TODO: Utwórz instancję Error z komunikatem błędu "Not found" i kodem błędu 404
// TODO: Wypisz wynik obsługi każdej odpowiedzi
}
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