Variables
Apprenez les variables dans Dart. Voici un exemple de création et d’initialisation d’une variable :
var name = 'Jack';Langage du code : JavaScript (javascript)
Les variables stockent des références. La variable nommée name contient une référence qui pointe vers un objet chaîne de caractères ayant pour valeur « Bob ».
Une référence est une adresse en mémoire. Pour faciliter le stockage des données, chaque zone mémoire reçoit une adresse unique, comme le numéro de porte d’une maison.

Le compilateur déduit automatiquement que le type de name est String, mais vous pouvez aussi spécifier manuellement le type pour modifier le résultat de l’inférence. Si une variable doit stocker des objets de plusieurs types, déclarez son type comme Object (utilisez dynamic si nécessaire).
Object name = 'Jack';Langage du code : JavaScript (javascript)
Une autre syntaxe consiste à indiquer explicitement le type (par exemple, nous savons qu’un nom est du texte stockable sous le type String, nous indiquons donc directement le type chaîne) :
String name = 'Jack';Langage du code : JavaScript (javascript)
Null safety (sécurité des valeurs null)
La null safety évite les erreurs causées par l’accès accidentel à des variables valant null ; ces erreurs sont appelées erreurs de déréférencement null (null dereference error). Elles surviennent quand vous accédez à une propriété ou appelez une méthode sur une expression dont le résultat est null.
Il existe une exception : si null supporte nativement cette propriété ou cette méthode (exemples : toString(), hashCode), aucune erreur ne survient. Grâce à la null safety, le compilateur Dart identifie ces erreurs potentielles à la compilation.
Les développeurs expérimentés savent que les erreurs de référence null sont très courantes. Si l’on peut empêcher ces erreurs dès la compilation, la stabilité et la robustesse du programme augmentent considérablement.
Exemple : supposons que vous vouliez récupérer la valeur absolue de la variable i de type int. Si i vaut null, exécuter i.abs() déclenchera une erreur de déréférencement null. Dans d’autres langages, ce code ne plante qu’à l’exécution ; le compilateur Dart interdit directement cet appel illégal et intercepte le problème en amont.
Trois changements majeurs apportés par la null safety :
1 Types acceptant null : quand vous spécifiez un type, vous contrôlez s’il autorise null en ajoutant un point d’interrogation à la fin du type.
String? name // Type nullable : peut valoir null ou une chaîne
String name // Type non nullable : interdit null, ne stocke que des chaînesLangage du code : JavaScript (javascript)
Dans beaucoup de langages, une variable string name peut contenir null, ce n’est pas autorisé en Dart. Pour stocker null, il faut utiliser le type string?.
2 Toute variable doit être initialisée avant utilisation. Les variables nullables ont par défaut la valeur null, ce qui équivaut à une initialisation automatique ; les types non nullables n’ont pas de valeur par défaut et vous devez leur attribuer manuellement une valeur initiale. Dart interdit d’accéder à des variables non initialisées pour éviter les défauts.
void main() {
int year; // Erreur : variable non nullable non initialisée
print(year); // Erreur de compilation : year n’a pas été initialisée
}
Langage du code : Dart (dart)
Ce code génère une erreur à la compilation
C:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:7:9: Error: Non-nullable variable 'year' must be assigned before it can be used.
print(year); // Erreur de compilation : year non initialisée
^^^^Langage du code : JavaScript (javascript)
En revanche, les variables nullables acceptent cette écriture :
void main() {
int? age; // Variable nullable, valeur par défaut null
print(age); // Affiche null sans erreur
//age = 18; // Affectation manuelle
//print(age); // Affiche 18
}Langage du code : JavaScript (javascript)
3 Interdiction d’accéder directement aux propriétés ou d’appeler des méthodes sur des expressions de type nullable. Il y a à nouveau des exceptions : les propriétés et méthodes natives de null (hashCode, toString()) restent autorisées.
void main() {
String? name; // Type nullable, valeur par défaut null
// Erreur : accéder directement à length échoue
// print(name.length);
// Correct : les méthodes natives de null sont autorisées
print(name.toString()); // Affiche "null"
print(name.hashCode); // Affiche un entier
// Correct : utiliser l’opérateur de sécurité null
print(name?.length); // Affiche null sans erreur
}Langage du code : PHP (php)
Valeurs par défaut
Les variables nullables sans affectation manuelle ont pour valeur initiale par défaut null. Même les variables numériques valent null par défaut,
car dans Dart, les nombres comme toutes les données sont fondamentalement des objets.
void main() {
int? lineCount;
assert(lineCount == null);
}Langage du code : JavaScript (javascript)
Attention : les vérifications
assert()sont ignorées en production ; pendant le développement, si la condition dansassert()est fausse, le programme lève une exception
Avec la null safety activée, les variables non nullables doivent être initialisées avant utilisation :
int lineCount = 0;
Les variables locales n’ont pas besoin d’être affectées sur la même ligne que leur déclaration, mais elles doivent recevoir une valeur avant leur utilisation. Le code ci-dessous est valide car Dart analyse qu’au moment d’exécuter print(), lineCount aura forcément une valeur non null :
int lineCount;
if (weLikeToCount) {
lineCount = countLines();
} else {
lineCount = 0;
}
print(lineCount);
Langage du code : Dart (dart)
Note : dans le code précédent, lineCount = countLines(); et lineCount = 0; sont des affectations sur lineCount, pas des utilisations. Utiliser signifie lire la valeur stockée. Par exemple le code ci-dessous génère une erreur :
void main() {
int lineCount;
print(lineCount);
}
Langage du code : Dart (dart)
Erreur de compilation

Les variables de niveau supérieur et les membres de classe utilisent l’initialisation différée : la logique d’affectation ne s’exécute que lors du premier accès à la variable.
Modificateur late sur les variables
Le modificateur late a deux cas d’usage principaux :
- Déclarer des variables non nullables qui recevront une valeur plus tard ;
- Mettre en place une initialisation différée des variables.
Dans la plupart des cas, l’analyse de flux de Dart vérifie si une variable non nullable a reçu une valeur valide avant utilisation. Cependant, l’analyse échoue dans certains cas, les plus courants étant les variables globales et les variables d’instance : le compilateur ne peut pas confirmer leur initialisation et signale une erreur.
Si vous êtes certain que la variable sera affectée avant son utilisation mais que le compilateur ne le détecte pas, ajoutez le modificateur late pour supprimer l’erreur :
Dans l’exemple ci-dessous, description est une variable globale, le compilateur ne peut pas vérifier si elle reçoit une valeur ; si vous êtes absolument sûr qu’elle sera renseignée, utilisez late :
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
Avertissement
Si vous déclarez une variable
latesans jamais lui attribuer de valeur, accéder à cette variable lèvera une exception à l’exécution.
Si vous donnez une valeur initiale lors de la déclaration d’une variable late, le code d’initialisation ne s’exécutera que la première fois que la variable est consultée. Cette initialisation différée est très utile dans deux situations :
- La variable risque de ne jamais être utilisée et son initialisation coûte beaucoup de ressources ;
- Lors de l’initialisation d’une variable d’instance, la logique d’initialisation doit accéder à
this.
Dans l’exemple ci-dessous, si la variable temperature n’est jamais utilisée, la fonction coûteuse readThermometer() ne s’exécutera jamais :
// readThermometer() n’est appelée qu’au premier accès à temperature
late String temperature = readThermometer(); // Initialisation différée
final et const
Si vous ne voulez pas que la valeur d’une variable soit modifiable, utilisez final ou const ; les deux peuvent être utilisés seuls ou associés à une annotation de type pour remplacer var.
- Les variables
finalne peuvent recevoir une valeur qu’une seule fois ; - Les variables
constsont des constantes de compilation (les variablesconstont implicitement le comportement definal).
Remarque
Les membres d’instance peuvent être marqués
finalmais pasconst; pour les constantes au niveau de la classe utilisezstatic const.
Exemples de déclaration de variables final :
final name = 'Jack'; // Sans annotation de type
final String nickname = 'Jason';
Vous ne pouvez pas modifier la valeur d’une variable final, le compilateur signale directement une erreur :
void main() {
final name = 'Jack'; // Sans annotation de type
final String nickname = 'Jason';
name = 'Alice'; // Erreur : une variable final ne peut être affectée qu’une fois
}
C:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:6:2: Error: Can't assign to the final variable 'name'.
name = 'Alice'; // Erreur : une variable final ne peut être affectée qu’une fois
const sert à définir des constantes de compilation. Si une constante est déclarée à l’intérieur d’une classe, ajoutez static pour écrire static const. Lors de la déclaration d’une variable const, la valeur affectée doit être déterminable à la compilation : nombres, littéraux de chaîne, autres variables const ou résultats d’opérations arithmétiques sur des constantes :
const bar = 1000000; // Unité de pression (dyne/cm²)
const double atm = 1.01325 * bar; // Pression atmosphérique standard
Le mot-clé const ne sert pas seulement à déclarer des variables constantes, vous pouvez aussi l’utiliser pour créer des objets constants ou définir des constructeurs produisant des instances constantes. N’importe quelle variable peut recevoir un objet constant comme valeur.
var foo = const [];
final bar = const [];
const baz = []; // Équivaut à const []
Dans les expressions d’affectation des variables const, le mot-clé const peut être omis comme dans l’exemple de baz ci-dessus.
Même si une variable a déjà stocké un objet constant, si elle n’est ni final ni const, sa référence peut être modifiée :
foo = [1, 2, 3]; // foo pointait initialement sur un tableau vide constant, on change sa référence
En revanche, les variables const interdisent toute réaffectation, le compilateur renvoie une erreur :
// Erreur d’analyse statique
baz = [42]; // Erreur : les variables const n’autorisent pas la réaffectation
Lors de la définition de constantes, vous pouvez utiliser les vérifications de type, le cast de type (is, as), les if de collection, les opérateurs de décomposition (..., ...?) :
void main() {
const Object i = 3; // i est une constante de type Object contenant une valeur int
const list = [i as int]; // Utilisation du cast de type
const map = {if (i is int) i: 'int'}; // Utilisation de is et if de collection
const set = {if (list is List<int>) ...list}; // Associé à l’opérateur de décomposition
}
Remarque
La référence d’un objet marqué
finalne peut pas être changée, mais ses champs internes peuvent être modifiés ; à l’inverse, un objetconstet toutes ses données internes sont totalement immuables.
Pour en savoir plus sur la création de collections constantes avec const, consultez la documentation sur les listes, maps et classes.
* Variables wildcard
Note de version : les variables wildcard nécessitent Dart 3.7 ou supérieur.
Les variables nommées _ sont des variables locales / paramètres non liés, elles ne servent que de marqueurs de position. Si une expression d’initialisation est présente, elle s’exécute mais vous ne pouvez pas lire la valeur stockée dans cette variable. Dans un même champ de portée, vous pouvez définir plusieurs variables _ sans conflit de noms.
Qu’est-ce qu’une variable wildcard ?
En Dart, le simple underscore _ est la variable wildcard :
- Elle sert à recevoir des valeurs inutilisées et signale au compilateur « je ne lirai ni n’utiliserai cette variable » ;
- Le compilateur ne génère pas d’avertissement « variable déclarée mais inutilisée » ;
- Il est interdit de lire
_(cela provoque une erreur), elle ne sert qu’à ignorer des données.
// On ne garde que la 1ᵉ et 3ᵉ valeur, la seconde est ignorée avec _
final [a, _, c] = [10, 20, 30];
print(a); // 10
print(c); // 30
// print(_); // Erreur, impossible de lire une variable wildcard
Les déclarations de niveau supérieur et les membres de classe qui gèrent la visibilité privée de la bibliothèque ne peuvent pas utiliser de variables wildcard. Elles ne sont autorisées qu’à l’intérieur des blocs, exemples ci-dessous :
- Déclaration de variables locales
void main() {
var _ = 1;
int _ = 2;
}
- Variable de boucle for
for (var _ in list) {}
- Paramètre de capture dans catch
try {
throw '!';
} catch (_) {
print('oops');
}
- Paramètres génériques, paramètres génériques de fonction
class T<_> {}
void genericFunction<_>() {}
takeGenericCallback(<_>() => true);
- Paramètres de fonction
Foo(_, this._, super._, void _()) {}
list.where((_) => true);
void f(void g(int _, bool _)) {}
typedef T = void Function(String _, String _);