Introduction à la Null Safety
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 23 sur 110.
L'une des sources de bogues les plus courantes en programmation est la tentative d'utiliser une valeur qui n'existe pas. En Dart, cette « absence de valeur » spéciale est représentée par null. La fonctionnalité de null safety de Dart vous aide à détecter ces erreurs avant même que votre code ne soit exécuté.
Sans null safety, n'importe quelle variable pourrait potentiellement être null, ce qui entraîne des plantages à l'exécution lorsque vous essayez de l'utiliser :
// Dans les anciennes versions de Dart (sans null safety)
String name; // Pourrait être null !
print(name.length); // Plante si name est nullAvec la sécurité nulle activée (Dart 2.12+), le compilateur fait la distinction entre les variables qui peuvent contenir null et celles qui ne le peuvent pas. Par défaut, les variables sont non-nullables - elles doivent toujours contenir une valeur valide :
String name = 'Alice'; // Doit avoir une valeur
print(name.length); // Sûr - name n'est jamais nullLe compilateur refusera de compiler du code où une variable non-nullable pourrait être null. Cela déplace la détection d'erreurs de l'exécution à la compilation, rendant vos programmes plus fiables. Dans les leçons à venir, vous apprendrez comment déclarer des types nullables lorsque vous en avez réellement besoin, ainsi que les opérateurs fournis par Dart pour manipuler en toute sécurité des valeurs potentiellement nulles.
Défi
FacileConstruisons un système simple de cartes de contact qui démontre l'importance des variables non-nullables. Vous allez créer un système où chaque contact doit avoir des informations valides et garanties.
Vous organiserez votre code en deux fichiers :
contact.dart: Définissez une classeContactqui représente les informations de contact d'une personne. Puisque nous travaillons avec la "null safety", chaque champ doit avoir une valeur valide - aucune donnée manquante n'est autorisée ! Votre classe doit avoir :- Un
String firstNamepour le prénom du contact - Un
String lastNamepour le nom de famille du contact - Un
String emailpour l'adresse e-mail du contact - Un
int phoneDigitspour le nombre de chiffres de leur numéro de téléphone - Un constructeur qui prend les quatre valeurs
- Un getter
fullNamequi retourne le prénom et le nom de famille combinés avec un espace entre eux - Une méthode
displayCard()qui affiche les informations du contact
- Un
main.dart: Importez votre classe de contact et créez deux contacts pour démontrer que tous les champs sont garantis d'avoir des valeurs :- Créez un contact avec le prénom
'Emma', le nom'Wilson', l'e-mail'emma@mail.com', et10chiffres de téléphone - Créez un contact avec le prénom
'James', le nom'Brown', l'e-mail'james@work.com', et11chiffres de téléphone - Appelez
displayCard()sur chaque contact dans l'ordre listé ci-dessus
- Créez un contact avec le prénom
La méthode displayCard() doit afficher les informations exactement dans ce format :
--- Contact Card ---
Name: [fullName]
Email: [email]
Phone digits: [phoneDigits]Remarquez comment chaque variable doit être initialisée avec une valeur réelle - c'est la "null safety" en action ! Le compilateur garantit que lorsque vous accédez à fullName, email, ou tout autre champ, il contiendra toujours des données valides.
Sortie attendue :
--- Contact Card ---
Name: Emma Wilson
Email: emma@mail.com
Phone digits: 10
--- Contact Card ---
Name: James Brown
Email: james@work.com
Phone digits: 11Aide-mémoire
Dart utilise la null safety pour prévenir les bugs causés par l'utilisation de valeurs qui n'existent pas. La valeur spéciale null représente l'absence de valeur.
Avec la null safety activée (Dart 2.12+), les variables sont non-nullables par défaut - elles doivent toujours contenir une valeur valide :
String name = 'Alice'; // Doit avoir une valeur
print(name.length); // Sûr - name n'est jamais nullLe compilateur empêche la compilation du code si une variable non-nullable pourrait être null, déplaçant la détection d'erreurs du moment de l'exécution vers le moment de la compilation.
Essayez vous-même
import 'contact.dart';
void main() {
// TODO: Créer le premier contact avec :
// - prénom : 'Emma'
// - nom : 'Wilson'
// - e-mail : 'emma@mail.com'
// - chiffres du téléphone : 10
// TODO: Créer le deuxième contact avec :
// - prénom : 'James'
// - nom : 'Brown'
// - e-mail : 'james@work.com'
// - chiffres du téléphone : 11
// TODO: Appeler displayCard() sur chaque contact dans l'ordre
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository