Słowo kluczowe late a bezpieczeństwo wartości null
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 26 z 110.
Czasami potrzebujesz zmiennej, która nie dopuszcza wartości null, ale nie możesz od razu przypisać jej wartości. Słowo kluczowe late mówi Dartowi: „Obiecuję zainicjalizować tę zmienną, zanim jej użyję”.
late String description;
void setup() {
description = 'Initialized later';
}
void main() {
setup();
print(description); // Działa – zainicjalizowano przed użyciem
}Bez late Dart zgłosiłby, że zmienna description nie została zainicjalizowana. Używając late, bierzesz na siebie odpowiedzialność za to, by przed dostępem do niej miała wartość. Jeśli spróbujesz ją odczytać przed zainicjalizowaniem, wystąpi błąd wykonania.
Częstym przypadkiem użycia są kosztowne obliczenia, które chcesz odłożyć do momentu, gdy będą rzeczywiście potrzebne:
class DataProcessor {
late List<int> data = _loadData();
List<int> _loadData() {
print('Loading data...');
return [1, 2, 3, 4, 5];
}
}
DataProcessor processor = DataProcessor();
// 'Loading data...' nie zostało jeszcze wypisane
print(processor.data); // Teraz dane są ładowane i wypisywaneMetoda _loadData() uruchamia się dopiero przy pierwszym dostępie do data, a nie podczas tworzenia obiektu. Ta leniwa inicjalizacja może poprawić wydajność, gdy wartość może nigdy nie być potrzebna.
Używaj late, gdy masz pewność, że zmienna zostanie zainicjalizowana przed użyciem, ale nie możesz tego zrobić podczas jej deklaracji. To obietnica składana kompilatorowi — złam ją, a program ulegnie awarii.
Wyzwanie
ŁatwyZbudujmy menedżer konfiguracji, który pokaże możliwości zmiennych late w zakresie odroczonej inicjalizacji. Utworzysz system, w którym kosztowne operacje konfiguracyjne będą wykonywane tylko wtedy, gdy konfiguracja będzie rzeczywiście potrzebna.
Podzielisz kod na dwa pliki:
config_manager.dart: Zdefiniuj klasęConfigManager, która obsługuje ustawienia aplikacji. Klasa powinna zawierać:String appNameprzekazane przez konstruktorlate String databaseUrl, które zostanie zainicjalizowane później za pomocą metody konfiguracjilate int maxConnectionsz leniwą inicjalizacją, która przy pierwszym dostępie wypisujeCalculating max connections...i zwraca100- Metodę
setupDatabase(String url), która inicjalizujedatabaseUrl - Metodę
displayConfig(), która wypisuje bieżącą konfigurację
main.dart: Zaimportuj menedżer konfiguracji i pokaż, jak działają zmienne late:- Utwórz obiekt
ConfigManagerz nazwą aplikacji'MyApp' - Wypisz
Config created - Wywołaj
setupDatabasez adresem URL'localhost:5432/mydb' - Wypisz
Accessing max connections... - Wypisz wartość
maxConnections - Wypisz
Accessing max connections again... - Ponownie wypisz wartość
maxConnections(zauważ, że komunikat o obliczaniu nie pojawia się ponownie) - Wywołaj
displayConfig()
- Utwórz obiekt
Metoda displayConfig() powinna wypisywać dane w następującym formacie:
--- Configuration ---
App: [appName]
Database: [databaseUrl]
Max Connections: [maxConnections]Zauważ, że leniwe obliczanie wartości maxConnections odbywa się tylko raz — przy pierwszym dostępie do niej. To właśnie zaleta użycia late z inicjalizatorem!
Oczekiwany wynik:
Config created
Accessing max connections...
Calculating max connections...
100
Accessing max connections again...
100
--- Configuration ---
App: MyApp
Database: localhost:5432/mydb
Max Connections: 100Spróbuj swoich sił
import 'config_manager.dart';
void main() {
// TODO: Utwórz ConfigManager z nazwą aplikacji 'MyApp'
// TODO: Wypisz 'Config created'
// TODO: Wywołaj setupDatabase z adresem URL 'localhost:5432/mydb'
// TODO: Wypisz 'Accessing max connections...'
// TODO: Wypisz wartość maxConnections
// TODO: Wypisz 'Accessing max connections again...'
// TODO: Wypisz ponownie wartość maxConnections
// (zwróć uwagę, że komunikat o obliczaniu nie pojawia się ponownie)
// TODO: Wywołaj displayConfig()
}
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