Typy dopuszczające null i niedopuszczające null
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 24 z 110.
Skoro już rozumiesz, dlaczego bezpieczeństwo null ma znaczenie, zobaczmy, jak zadeklarować zmienne, które mogą przechowywać wartość null. W Dart możesz sprawić, że typ będzie dopuszczał wartość null, dodając ? po nazwie typu.
String name = 'Alice'; // Nieakceptujący wartości null — zawsze musi mieć wartość
String? nickname; // Akceptujący wartość null — może być null lub typu String
print(name); // Alice
print(nickname); // nullKluczowa różnica polega na tym, że typy niepuste gwarantują istnienie wartości, natomiast typy dopuszczające wartość null jawnie pozwalają na jej brak. To rozróżnienie dotyczy wszystkich typów:
int count = 10; // Musi mieć wartość
int? optionalCount; // Może mieć wartość null
List<String> items = []; // Musi być listą (może być pusta)
List<String>? maybeItems; // Może mieć wartość null (lista może w ogóle nie istnieć)Zauważ, że pusta lista [] różni się od null. Pusta lista istnieje, ale niczego nie zawiera; null oznacza, że żadna lista w ogóle nie istnieje.
Kompilator ściśle egzekwuje te zasady. Nie możesz przypisać wartości null do zmiennej, która nie dopuszcza wartości null, ani użyć zmiennej, która dopuszcza wartość null, w miejscu, w którym oczekiwana jest zmienna niedopuszczająca wartości null, bez uprzedniego sprawdzenia, czy jej wartość to null:
String? maybeName = 'Bob';
// String definite = maybeName; // Błąd! Nie można przypisać wartości dopuszczającej null do typu niedopuszczającego nullW następnej lekcji poznasz operatory, które Dart udostępnia, aby bezpiecznie pracować z wartościami dopuszczającymi null.
Wyzwanie
ŁatwyZbudujmy system listy filmów do obejrzenia, który pokazuje różnicę między informacjami wymaganymi a opcjonalnymi, używając typów dopuszczających i niedopuszczających wartości null.
Utworzysz dwa pliki, aby uporządkować swój kod:
movie.dart: Zdefiniuj klasęMovie, która reprezentuje film na Twojej liście do obejrzenia. Każdy film musi mieć tytuł i rok premiery (są one zawsze wymagane), ale niektóre dodatkowe informacje mogą być niedostępne dla każdego filmu. Twoja klasa powinna zawierać:- Pole
String title, które nie dopuszcza wartości null — każdy film musi mieć tytuł - Pole
int year, które nie dopuszcza wartości null — każdy film musi mieć rok premiery - Pole
String? director, które dopuszcza wartość null — reżyser może być nieznany - Pole
double? rating, które dopuszcza wartość null — nie wszystkie filmy zostały już ocenione - Konstruktor, który przyjmuje
titleiyearjako wymagane parametry - Metodę
displayInfo(), która wyświetla informacje o filmie, pokazującUnknown, gdy brakuje reżysera, orazNot rated, gdy brakuje oceny
- Pole
main.dart: Zaimportuj swoją klasę filmu i utwórz krótką listę do obejrzenia, pokazującą zarówno kompletne, jak i niekompletne dane filmów:- Utwórz film z tytułem
'Inception'i rokiem2010, a następnie ustaw jego reżysera na'Christopher Nolan'i ocenę na8.8 - Utwórz film z tytułem
'The Matrix'i rokiem1999, a następnie ustaw tylko jego ocenę na8.7(pozostaw reżysera jako null) - Utwórz film z tytułem
'Upcoming Film'i rokiem2025(pozostaw zarówno reżysera, jak i ocenę jako null) - Wywołaj
displayInfo()dla każdego filmu, w podanej wyżej kolejności
- Utwórz film z tytułem
Metoda displayInfo() powinna wyświetlać informacje w dokładnie takim formacie:
[title] ([year])
Director: [director or "Unknown"]
Rating: [rating or "Not rated"]Zwróć uwagę, że pola niedopuszczające wartości null (title i year) zawsze mają przypisane wartości, podczas gdy pola dopuszczające wartość null (director? i rating?) mogą pozostać nieustawione. Odzwierciedla to rzeczywiste sytuacje, w których niektóre dane są niezbędne, a inne opcjonalne.
Oczekiwany wynik:
Inception (2010)
Director: Christopher Nolan
Rating: 8.8
The Matrix (1999)
Director: Unknown
Rating: 8.7
Upcoming Film (2025)
Director: Unknown
Rating: Not ratedSpróbuj swoich sił
import 'movie.dart';
void main() {
// TODO: Utwórz film o tytule 'Inception' z roku 2010
// Następnie ustaw jego reżysera na 'Christopher Nolan', a ocenę na 8.8
// TODO: Utwórz film o tytule 'The Matrix' z roku 1999
// Następnie ustaw tylko jego ocenę na 8.7 (pozostaw director jako null)
// TODO: Utwórz film o tytule 'Upcoming Film' z roku 2025
// Pozostaw zarówno director, jak i rating jako null
// TODO: Wywołaj displayInfo() dla każdego filmu po kolei
}
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