Non nullable (par défaut)
L' expérience non nullable (par défaut) se trouve actuellement sur nullsafety.dartpad.dev .
Gardez à l'esprit que vous pouvez lire les spécifications complètes ici et la feuille de route complète ici .
Que signifie non-nullable par défaut?
void main() {
String word;
print(word); // illegal
word = 'Hello, ';
print(word); // legal
}
Comme vous pouvez le voir ci-dessus, une variable étant non nullable par défaut signifie que chaque variable qui est déclarée normalement ne peut pas l' être null. Par conséquent, toute opération accédant à la variable avant son affectation est illégale.
De plus, l'attribution nullà une variable non nullable n'est pas non plus autorisée:
void main() {
String word;
word = null; // forbidden
world = 'World!'; // allowed
}
Comment cela m'aide-t-il?
Si une variable n'est pas nullable , vous pouvez être sûr qu'elle ne l'est jamais null. Pour cette raison, vous n'avez jamais besoin de le vérifier à l'avance.
int number = 4;
void main() {
if (number == null) return; // redundant
int sum = number + 2; // allowed because number is also non-nullable
}
Rappelles toi
Les champs d'instance dans les classes doivent être initialisés s'ils ne peuvent pas être annulés:
class Foo {
String word; // forbidden
String sentence = 'Hello, World!'; // allowed
}
Voir lateci - dessous pour modifier ce comportement.
Types nullables ( ?)
Vous pouvez utiliser des types nullables en ajoutant un point d'interrogation ?à un type de variable:
class Foo {
String word; // forbidden
String? sentence; // allowed
}
Une variable nullable n'a pas besoin d'être initialisée avant de pouvoir être utilisée. Il est initialisé comme nullpar défaut:
void main() {
String? word;
print(word); // prints null
}
!
L'ajout !à une variable egénérera une erreur d'exécution si eest nul et sinon le convertira en une valeur non nulle v.
void main() {
int? e = 5;
int v = e!; // v is non-nullable; would throw an error if e were null
String? word;
print(word!); // throws runtime error if word is null
print(null!); // throws runtime error
}
late
Le mot-clé latepeut être utilisé pour marquer des variables qui seront initialisées ultérieurement , c'est-à-dire non pas quand elles sont déclarées mais quand elles sont accédées. Cela signifie également que nous pouvons avoir des champs d'instance non nullables qui sont initialisés plus tard:
class ExampleState extends State {
late String word; // non-nullable
@override
void initState() {
super.initState();
// print(word) here would throw a runtime error
word = 'Hello';
}
}
L'accès wordavant son initialisation générera une erreur d'exécution.
late final
Les variables finales peuvent désormais également être marquées tardivement:
late final int x = heavyComputation();
Ici heavyComputationne sera appelé qu'une fois xaccessible. De plus, vous pouvez également déclarer un late finalsans initialiseur, ce qui équivaut à n'avoir qu'une latevariable, mais il ne peut être attribué qu'une seule fois.
late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden
Notez que toutes les variables de niveau supérieur ou statiques avec un initialiseur seront désormais évaluées late, peu importe si elles le sont final.
required
Anciennement une annotation ( @required), désormais intégrée comme modificateur. Il permet de marquer tout paramètre nommé (pour les fonctions ou les classes) comme required, ce qui les rend non nullables:
void allowed({required String word}) => null;
Cela signifie également que si un paramètre ne doit pas être nullable , il doit être marqué comme requiredou avoir une valeur par défaut:
void allowed({String word = 'World'}) => null;
void forbidden({int x}) // compile-time error because x can be null (unassigned)
=>
null;
Tout autre paramètre nommé doit être nullable :
void baz({int? x}) => null;
?[]
L' ?[]opérateur de reconnaissance null a été ajouté pour l'opérateur d'index []:
void main() {
List<int>? list = [1, 2, 3];
int? x = list?[0]; // 1
}
Voir également cet article sur la décision de syntaxe .
?..
L'opérateur en cascade maintenant dispose également d' un nouvel opérateur courant nul: ?...
Il entraîne l'exécution des opérations en cascade suivantes uniquement si le destinataire n'est pas nul . Par conséquent, le ?..doit être le premier opérateur en cascade dans une séquence en cascade:
void main() {
Path? path;
// Will not do anything if path is null.
path
?..moveTo(3, 4)
..lineTo(4, 3);
// This is a noop.
(null as List)
?..add(4)
..add(2)
..add(0);
}
Never
Pour éviter toute confusion: ce n'est pas quelque chose dont les développeurs doivent s'inquiéter. Je tiens à le mentionner par souci d'exhaustivité.
Neverva être un type comme celui qui existait précédemment Null( nonnull ) défini dans dart:core. Ces deux classes ne peuvent pas être étendues, implémentées ou mélangées, elles ne sont donc pas destinées à être utilisées.
Essentiellement, Neversignifie qu'aucun type n'est autorisé et Neverlui - même ne peut pas être instancié.
Rien que Neverdans un ne List<Never>satisfait la contrainte de type générique de la liste, ce qui signifie qu'elle doit être vide . List<Null>, cependant, peut contenir null:
// Only valid state: []
final neverList = <Never>[
// Any value but Never here will be an error.
5, // error
null, // error
Never, // not a value (compile-time error)
];
// Can contain null: [null]
final nullList = <Null>[
// Any value but Null will be an error.
5, // error
null, // allowed
Never, // not a value (compile-time error)
Null, // not a value (compile-time error)
];
Exemple: le compilateur déduira List<Never>pour un vide const List<T> .
Nevern'est pas censé être utilisé par les programmeurs en ce qui me concerne.
Neverpeuvent être utilisés?