Академический Документы
Профессиональный Документы
Культура Документы
Language samples
A brief, example-based introduction to the Dart language.
Language tour
A more thorough (yet still example-based) introduction to the Dart language.
Dart efficace
Best practices for building consistent, maintainable, efficient Dart code.
Library tour
An example-based introduction to the major features in the Dart SDK's core
libraries.
1
A tour of the Dart language
Contents
2
Les exceptions
o Throw
o Catch
o Finally
Les Classes
o Utilisation des membres de la classe
o Utiliser des constructeurs
o Obtenir le type d'un objet
o Variables d'instance
o Les constructeurs
o Les méthodes
o Classes abstraites
o Interfaces implicites
o Héritage de classe
o Les types énumérés
o Ajout de fonctionnalités à une classe: mixins
o Variables et méthodes de classe
Les génériques
o Pourquoi utiliser des génériques?
o Utiliser une collection de littéraux
o Utiliser des types paramétrés avec les constructeurs
o Collections génériques et types qu'elles contiennent
o Restreindre le type paramétré
o Utiliser des méthodes génériques
Bibliothèques et visibilité
o Utiliser les librairies
o Implémentation de librairies
Asynchronisme
o Gestion des Futures
o Déclarer des fonctions async
o Traitement des flux
Les générateurs
Les classes appelables
Isolats
Typedefs
Métadonnées
Commentaires
o Commentaires sur une seule ligne
o Commentaires multilignes
o Commentaires de la documentation
Résumé
3
Cette page vous montre comment utiliser chaque fonction majeure de Dart,
depuis les variables et opérateurs jusqu'aux classes et bibliothèques, avec
l'hypothèse que vous savez déjà programmer dans un autre langage.
To learn more about Dart’s core libraries, see the library tour. Chaque fois que
vous voulez plus de détails sur une fonctionnalité du langage,
consulter Spécification du langage Dart.
Ouvrir un DartPad
// Define a function.
printInteger(int aNumber) {
print('The number is $aNumber.'); // Print to console.
}
Voici ce que ce programme utilise qui s’applique à toutes (ou presque) les
applications Dart:
4
print()
'...'(ou"...")
Concepts importants
Tout au long de votre apprentissage du langage Dart, tâchez de conservez ce
qui suit en tête:
Tout ce que vous pouvez placer dans une variable est un objetet
chaque objet est une instance d'une class. Les nombres pairs, les
fonctions et nullsont des objets. Tous les objets héritent de la
class Object.
Bien que Dart soit fortement typé, les annotations de type sont
facultatives parce que Dart peut déduire des types. Dans le code ci-
dessus, la variable number est reconnue comme étant de type int.
Quand vous voulez dire explicitement indiquer qu'aucun type n'est
attendu, utiliser le type spécial dynamic.
Dart supporte les types génériques, comme List<int>(une liste
d'entiers) ou List<dynamic>(une liste d'objets de tout type).
Dart prend en charge les fonctions de niveau supérieur (telles
que main()), aussi bien que fonctions liées à une classe ou à un objet
( staticet instance methods, respectivement). Vous pouvez également
créer des fonctions dans les fonctions (imbriquée ou fonction locale).
5
De même, Dart prend en charge les variables globales, ainsi que des
variables lié à une classe ou à un objet (variables statiques et
d'instance). Exemple les variables sont parfois appelées champs ou
propriétés.
Contrairement à Java, Dart ne reconnait pas les mots-
clés public, protected, et private. Si un identifiant commence par un trait
de soulignement (_), alors ils s'agit d'une variable ou méthode privée à
sa bibliothèque. Pour plus de détails, voir Bibliothèques et visibilité .
Les Identifiants peut commencer par une lettre ou un trait de
soulignement (_), suivi de n'importe quelle combinaison de caractères,
de chiffres et traits de soulignement (_).
Dart gère les expressions (qui ont des valeurs d'exécution) et
les instructions (qui n'en n'ont pas). Par exemple, l'expression
conditionnelle condition ? expr1 : expr2 prend la une valeur
de expr1 ou expr2. Par contre l'instruction if-else statement, n'a aucune
valeur. Une instruction contient souvent une ou plusieurs expressions,
mais une expression ne peut pas contenir directement une instruction.
Les outils de Dart peuvent signaler deux types de problèmes: les
avertissements (warnings) et les erreurs (errors). Les avertissements ne
sont que des indications que votre code pourrait ne pas fonctionner,
mais ils n’empêchent pas votre programme de s’exécuter. Les erreurs
peuvent être soit au moment de la compilation ou de l'exécution. Une
erreur de compilation empêche le code d'exécuter du tout; une erreur
d'exécution entraîne la levée d'une exception pendant l'exécution du
code.
Keywords
Le tableau suivant répertorie les mots que le langage Dart traite spécialement.
6
catch false new true
do if set 2 yield 3
Mots indicés 1 sont des mots-clés contextuels , qui ont un sens que
dans des endroits spécifiques. Ce sont des identifiants valides partout.
Mots indicés 2 sont des identifiants intégrés . Pour simplifier la
conversion du code JavaScript en Dart, ces mots-clés sont des
identifiants valables dans la plupart des endroits, mais ils ne peuvent
pas être utilisés comme noms de classe ou de type, ni comme préfixes
d’importation.
Mots indicés 3sont des mots nouveaux, réservés et liés à au support
asynchrone qui a été ajouté après la sortie de Dart 1.0. Vous ne pouvez
pas utiliser await ou yieldcomme identifiant dans tout corps de fonction
marqué avec async, async*, ou sync*.
Tous les autres mots du tableau sont des mots réservés , qui ne peuvent pas
être utilisés.
Variables
Voici un exemple de création et d’initialisation d’une variable:
7
Le type de la variable nameest convertie par déduction en String, mais vous
pouvez changer ce type en le spécifiant. Si un objet n'est pas limité à un seul
type, spécifiez le type Object ou dynamic conformément directives de
conception.
Une autre option consiste à déclarer explicitement le type qui serait déduit:
Default value
Les variables non initialisées ont une valeur initiale null. Même variables avec
des types numériques sont initialement nuls, parce que les nombres - comme
tout dans Dart - sont des objets.
int lineCount;
assert(lineCount == null);
Remarque: Les variables d'instance peuvent être final mais pas const. Les
variables d'instance finales doivent être initialisées avant l’exécution du
constructeur - à la déclaration de la variable, par un paramètre constructeur,
ou dans le constructeur l'initialisation par liste.
8
Vous ne pouvez pas changer la valeur d’une variable finale:
Utilisez const pour les variables que vous voulez qui peuvent être compilé
comme des constantes. Si la variable const est au niveau de la classe,
marquez-la static const. Où vous déclarez la variable, définissez la valeur qui
puisse être compilé en tant que constante comme un nombre ou une chaîne
littérale, une autre variable const, ou le résultat d'une opération arithmétique
sur des nombres constants:
Le mot clé const n'est pas juste utilisée pour déclarer des variables
constantes. Vous pouvez également l'utiliser pour créer
des valeursconstantes, ainsi que pour déclarer des constructeurs créant des
valeurs constantes. Toute variable peut avoir une valeur constante.
Vous pouvez changer la valeur d'une variable non finale, non constante,
même si elle avait une valeur const:
Pour plus d'informations sur l'utilisation de const pour créer des valeurs
constantes, voir Les listes, Les tableaux associatifs, et Les classes .
9
Built-in types
Le langage Dart prend en charge les types suivants:
les nombres
les chaînes de caractères
les booléens
les listes (également appelées arrays)
sets
les tableaux associatifs
les runes (pour exprimer des caractères Unicode dans une chaîne)
les symboles
Numbers
Dart numbers come in two flavors:
int
double
Les int et les double sont des sous type de num.Le type num inclut des
opérateurs de base tels que +, -, / et *, et c'est aussi où vous
trouverez abs(), ceil(), et floor(), entre autres méthodes. (Les opérateurs
binaires, tels que >>, sont définis dans la class intuniquement.) Si num et ses
sous-types ne correspondent pas à ce que vous recherchez, la
bibliothèque dart:math le pourrait peut-être.
10
Les entiers sont des nombres sans virgule décimale. Voici quelques exemples
de définir des littéraux entiers:
var x = 1;
var hex = 0xDEADBEEF;
var y = 1.1;
var exponents = 1.42e5;
Note de version: Avant Dart 2.1, l’utilisation d’un littéral entier à la place d'un double était
une erreur.
Le type int permet le décalage binaire traditionnel (<<, >>), ainsi que les
opérateurs ET (&) et OU (|). Par exemple:
Les nombres littérales sont des constantes à la compilation ainsi que toute
expression produite à partir de constantes à la compilation.
11
const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;
Strings
Une chaîne Dart est une séquence de caractères UTF-16. Vous pouvez
utiliser soit guillemets simples ou doubles pour créer une chaîne:
Remarque: L'appel == teste si deux objets sont équivalents. Deux les chaînes
sont équivalentes si elles contiennent la même séquence de caractères.
12
Une autre façon de créer une chaîne multiligne: utilisez un guillemet triple
avec guillemets simples ou doubles:
var s1 = '''
You can create
multi-line strings like this one.
''';
Voir Les runes pour plus de détails sur la façon d'exprimer les caractères
Unicode dans une chaîne.
Les chaînes littérales sont des constantes à la compilation ainsi que toute
expression produite à partir de constantes à la compilation.
13
Les booléens
Pour représenter les valeurs booléennes, Dart a un type nommé bool.
Seulement deux les objets ont le type bool: les littéraux booléens true et false,
qui sont également des constantes à la compilation.
La sécurité de type Dart signifie que vous ne pouvez pas utiliser de code
comme if (nonbooleanValue) ou assert (nonbooleanValue). Au lieu de cela,
vérifiez explicitement les valeurs, comme ceci:
Lists
Peut-être la collection la plus commune dans presque tous les langages de
programmation est le tableau, ou groupe ordonné d'objets. Dans Dart, les
tableaux sont des objets List, de sorte que la plupart des gens les
appellent listes.
Dart list literals look like JavaScript array literals. Here’s a simple Dart list:
Remarque: Dart infers that list est de type List<int>. Si vous essayez d’ajouter des objets
non-entiers à cette liste, l'analyseur ou le moteur d'exécution génère une erreur. Pour plus
d'informations, lisez la page concernant la déduction de type
14
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
Pour créer une liste qui est une constante de compilation, ajouter constavant la
liste littérale:
Dart 2.3 introduced the spread operator (...) and the null-aware spread
operator (...?), which provide a concise way to insert multiple elements into a
collection.
For example, you can use the spread operator (...) to insert all the elements
of a list into another list:
If the expression to the right of the spread operator might be null, you can
avoid exceptions by using a null-aware spread operator (...?):
var list;
var list2 = [0, ...?list];
assert(list2.length == 1);
For more details and examples of using the spread operator, see the spread
operator proposal.
Dart 2.3 also introduced collection if et collection for, which you can use to
build collections using conditionals (if) and repetition (for).
var nav = [
'Home',
'Furniture',
'Plants',
if (promoActive) 'Outlet'
];
15
Here’s an example of using collection for to manipulate the items of a list
before adding them to another list:
For more details and examples of using collection if and for, see the control
flow collections proposal.
Sets
A set in Dart is an unordered collection of unique items. Dart support for sets is
provided by set literals and the Set.
Version note: Although the Set type has always been a core part of Dart, set literals were
introduced in Dart 2.2.
Remarque: Dart infers that halogens a le type Set<String>. If you try to add the wrong
type of value to the set, the analyzer or runtime raises an error. For more information, read
about déduction de type
Set or map? The syntax for map literals is similar to that for set literals. Because map literals
came first, {} defaults to the Maptype. If you forget the type annotation on {} or the variable
it’s assigned to, then Dart creates an object of type Map<dynamic, dynamic>.
16
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
To create a set that’s a compile-time constant, add const before the set literal:
As of Dart 2.3, sets support spread operators (... et ...?) and collection ifs
and fors, just like lists do. For more information, see the list spread
operator et list collection operator discussions.
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
17
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
Remarque: Dart infers that gifts a le type Map<String, String> et nobleGases has the
type Map<int, String>. Si vous essayez d'ajouter le mauvais type de valeur au tableau,
l'analyseur ou le moteur d'exécution génère une erreur. Pour plus d'informations, lisez à
propos de type inference.
Vous pouvez créer les mêmes en utilisant l'un des constructeurs de l'objet
Map:
Remarque: Vous pourriez vous attendre à voir new Map() au lieu de juste Map(). À partir de
Dart 2, le mot clé new est facultatif. Pour plus de détails, voir Utiliser des constructeurs .
Si vous recherchez une clé qui ne figure pas dans le tableau, vous obtenez
une valeur null en retour:
18
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);
Pour créer un tableau qui soit qui est une constante de compilation,
ajouter const avant déclaration littérale du tableau associatif:
As of Dart 2.3, maps support spread operators (... et ...?) and collection if
and for, just like lists do. For details and examples, see thespread operator
proposal and the control flow collections proposal.
Runes
Dans Dart, les runes sont les caractères UTF-32 d'une chaîne.
Unicode définit une valeur numérique unique pour chaque lettre, chiffre,
symbole utilisé dans tous les systèmes d’écriture du monde. Parce qu'une
chaîne Dart est une séquence de caractères UTF-16, l'expression de valeurs
Unicode 32 bits dans une chaîne nécessite syntaxe spéciale.
La classe String a plusieurs propriétés que vous pouvez utiliser pour extraire
des informations sur les runes. les propritétés codeUnitAtet codeUnit retournent
un caractère 16 bits. Utilisez la propriété runes pour obtenir les runes d'une
chaîne.
19
L’exemple suivant illustre la relation entre les runes, caractères 16 bits et
caractères 32 bits. Cliquez sur le bouton Exécuter pour voir les runes en
action.
Remarque: Soyez prudent lorsque vous manipulez des runes à l'aide des
fonctions de l'objet List. Cette approche peut facilement échouer, en fonction
de la langue, du jeu de caractères et de l'opération. Pour plus d'informations,
voir Comment inverser une chaîne dans Dart? sur Stack Overflow.
Symbols
Un objet Symbol représente un opérateur, un identifiant ou une classe déclaré
dans un programme Dart. Vous n’aura peut-être jamais besoin d’utiliser des
symboles, mais ils sont d’une valeur inestimable pour les API qui doivent faire
référence aux identifiants par leur nom. En Dart on utilise les symboles pour
savoir par exemple si la méthode d'un classe existe. La classe (et non l'object)
et la méthode dispose tous les deux d'un symbole unique.
#radix
#bar
Functions
Dart est un vrai langage orienté objet, donc même les fonctions sont des
objets et avoir un type, Function.Cela signifie que les fonctions peuvent être
assignées à des variables ou transmises en tant qu'arguments à d'autres
fonctions. Vous pouvez également appeler une instance d'une classe Dart
comme si c'était une fonction. Pour plus de détails, voir Les classes
appelables.
Bien qu'optionnelle, Dart recommande une annotations de type pour les API
publiques, la fonction fonctionne toujours si vous omettez les types:
isNoble(atomicNumber) {
20
return _nobleGases[atomicNumber] != null;
}
Pour les fonctions contenant une seule expression, vous pouvez utiliser un
raccourci syntaxe:
La syntaxe => expr est un raccourci pour { return expr; } La notation => est
parfois appelée syntaxe fléchée.
Remarque: Only an expression - et pas une instruction—can appear between the arrow (=>)
and the semicolon (;). For example, you can’t put an if statement ici, mais vous pouvez
utiliser une conditional expression.
Remarque: Some APIs — notably Flutter: widget constructors — use only named
parameters, even for parameters that are mandatory. See the next section for details.
Named parameters
Lors de l'appel d'une fonction, vous pouvez spécifier des paramètres nommés
à l'aide de paramName: value. Par exemple:
21
If someone tries to create a Scrollbar without specifying the child argument,
then the analyzer reports an issue.
Positional parameters
Encadrer des paramètres de fonction par des crochets [] les marque comme
facultatifs.
Voici un exemple de définition des valeurs par défaut pour les paramètres
nommés:
22
Note de dépréciation: L'ancienne version de Dart utilisait le caractère : au
lieu de = pour définir les valeurs par défaut des paramètres nommés. La raison
en est qu'à l'origine, seul : was supported for named parameters. That support
might be deprecated, so we recommend that you d'utiliser = pour spécifier
les valeurs par défaut.
L'exemple suivant montre comment définir les valeurs par défaut pour les
paramètres positionnés:
assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');
void doStuff(
{List<int> list = const [1, 2, 3],
Map<String, String> gifts = const {
'first': 'paper',
'second': 'cotton',
'third': 'leather'
}}) {
print('list: $list');
print('gifts: $gifts');
}
23
La fonction main()
Chaque application doit avoir une fonction de niveau supérieur main() function,
which serves as the entrypoint to the app. The main()function returns void and
has an optional List<String> parameter for arguments.
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
Transmission de fonction
Vous pouvez transmettre une fonction en tant que paramètre à une autre
fonction. Par exemple:
24
list.forEach(printElement);
Vous pouvez également affecter une fonction à une variable, telle que:
Fonctions anonymes
La plupart des fonctions sont nommées, telles que main() ou printElement().
Vous pouvez également créer une fonction sans nom appelée fonction
anonyme , ou parfois lambdaou closure. Vous pouvez affecter une fonction
anonyme à une variable. Vous pouvez également l'ajouter ou la supprimer
d'une collection.
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
25
Lexical scope
Dart est un langage à portée lexicale, ce qui signifie que la portée de les
variables sont déterminées statiquement, simplement par la disposition du
code. Vous pouvez "suivre les accolades vers l'extérieur" pour voir si une
variable est dans portée.
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
Closures lexicales
Une closure est un objet fonction qui a accès aux variables de sa portée
lexicale, même lorsque la fonction est utilisée en dehors de sa portée
d'origine.
26
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
class A {
static void bar() {} // A static method
void baz() {} // An instance method
}
void main() {
var x;
Return values
Toutes les fonctions renvoient une valeur. Si aucune valeur de retour n'est
spécifiée, le déclaration return null;est implicitement ajouté au corps de la
fonction.
foo() {}
assert(foo() == null);
Operators
Dart définit les opérateurs indiqués dans le tableau suivant. Vous pouvez
remplacer plusieurs de ces opérateurs, comme décrit dans Surcharge des
opérateurs .
Description Opérateur
multiplicatif * / % ~/
additif + -
ET binaire &
XOR binaire ^
OU binaire |
égalité == !=
28
Description Opérateur
ET logique &&
OU logique ||
si null ??
cascade ..
Lorsque vous utilisez des opérateurs, vous créez des expressions. Voici
quelques exemples des expressions d'opérateur:
a++
a + b
a = b
a == b
c ? a : b
a is T
Dans la table des opérateurs , chaque opérateur a une priorité plus élevée que
les opérateurs dans les lignes qui le suivent. Par exemple, l'opérateur
multiplicatif %a une priorité plus élevée (et donc sera exécuté avant) que
l'opérateur d'égalité ==, qui lui-même a une priorité plus élevée que l'opérateur
logique AND &&. Cette la priorité signifie que les deux lignes de code suivantes
exécutent la même chose:
29
Opérateurs arithmétiques
Dart supports the usual arithmetic operators, as shown in the following table.
Opérateur Description
+ Ajouter
– Soustraire
/ Diviser
~/ Diviser, renvoyer un résultat entier
% Récupère le reste d'une division entière
(modulo)
Exemple:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder
Opérateur Description
30
Opérateur Description
Exemple:
var a, b;
a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1
a = 0;
b = a++; // Increment a AFTER b gets its value.
assert(a != b); // 1 != 0
a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1
a = 0;
b = a--; // Decrement a AFTER b gets its value.
assert(a != b); // -1 != 0
31
Égalité et opérateurs relationnels
Le tableau suivant répertorie les significations des opérateurs d'égalité et
relationnels.
Opérateur Description
1. Si x ou y est null alors renvoie true si les deux sont nuls et false si
seulement l'un est nul.
2. Renvoie le résultat de l'invocation de la méthode x.==(y). (C'est vrai, des
opérateurs tels que == sont des méthodes qui sont invoquées sur leur
première opérande. Vous pouvez même remplacer plusieurs
opérateurs, y compris ==comme vous verrez dans Surcharge des
opérateurs .)
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
32
Opérateurs de test de type
Les opérateurs as, is et is! sont pratiques pour vérifier les types durant
l’exécution du programme.
Opérateur Description
Le résultat de obj is T est vrai si obj implémente l'interface spécifié par T. Par
exemple, obj is Object est toujours vrai.
Utilisez l'opérateur as pour convertir un objet d'un type vers un autre type. En
général, vous devriez l’utiliser comme raccourci d'une utilisation de
l'opérateur is suivi d'une expression utilisant cet objet. Par exemple,
considérons le code suivant:
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
Remarque: Le code n’est pas équivalent. Si emp est nul ou pas une personne,
le premier exemple (avec is) ne fait rien; le seconde (avec as) lève une
exception.
Opérateurs d'assignation
Comme vous l’avez déjà vu, vous pouvez attribuer des valeurs à l’aide de
l'opérateur =. Pour n'affecter une valeur que si elle est nulle, Utilisez
l'opérateur ??=.
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the
same
33
b ??= value;
= –= /= %= >>= ^=
Pour un a op= b a = a op b
opérateur op:
Exemple: a += b a = a + b
Opérateurs logiques
You can invert or combine boolean expressions using the logical operators.
Opérateur Description
34
Opérateurs binaires et de décalage
You can manipulate the individual bits of numbers in Dart. Usually, you’d use
these bitwise and shift operators with integers.
Opérateur Description
& ET
| OU
^ EOR
Expressions conditionnelles
Dart a deux opérateurs qui vous permettent d’évaluer de manière concise des
expressions qui pourraient autrement nécessiter un instruction if-else:
Si condition est vrai, évalue expr1 (et retourne sa valeur); sinon, évalue
et renvoie la valeur de expr2.
expr1 ?? expr2
35
Si expr1 est non-null, renvoie sa valeur; sinon, évalue et renvoie la
valeur de expr2.
Quand vous devez assigner une valeur basé sur une expression booléenne,
envisager d'utiliser l'opérateur ternaire ?:.
L’exemple précédent aurait pu être écrit d’au moins deux autres manières,
mais pas aussi succinctement:
36
L'exemple précédent est équivalent à:
Faites attention à construire votre cascade sur une fonction qui retourne un
objet réel. Par exemple, le code suivant échoue:
var sb = StringBuffer();
sb.write('foo')
..write('bar'); // Error: method 'write' isn't defined
for 'void'.
Other operators
Vous avez vu sans doute déjà croisé les opérateurs restants présenté ci-
dessous:
37
Opérateur Nom Description
. Accès aux membres Fait référence à une propriété d'une
expression; Exemple: foo.bar sélectionne la
propriété bar de l'expression foo
?. Accès conditionnel Comme ., mais l'opérande le plus à gauche
aux membres peut être nul; Exemple: foo?.bar sélectionne
la propriété bar de l'expression foo sauf
si foo est nul (auquel cas la valeur
de foo?.bar est nulle)
Pour plus d'informations sur les opérateurs ., ?., et .., voir Les classes .
if et else
for
while et do-while
break et continue
switch et case
assert
If and else
Dart supporte l'instruction if et son instruction optionnelle else, comme
l'échantillon de code suivant montre. Voir aussi Les expressions
conditionnelles .
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
38
Contrairement à JavaScript, les conditions doivent utiliser des valeurs
booléennes, rien d'autre. Voir Booleanspour plus d'informations.
For loops
Vous pouvez itérer avec la standard boucle for. Par exemple:
Les Closures de Dart pour les boucles for capturent la valeur de l'index, et
évite ainsi un piège commun trouvé dans JavaScript. Par exemple,
considérons:
Les classes itérables telles que List et Set prennent également en charge la
form for-in de l'itération:
39
Les boucle While et do-while
Une boucle while évalue la condition avant l'itération:
while (!isDone()) {
doSomething();
}
do {
printLine();
} while (!atEndOfPage());
Break et continue
Utilisez break pour sortie de la boucle:
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
40
Switch and case
Dans Dart, switch réalise les comparaison avec des entiers, des chaînes ou
toute compilation constantes utilisant l'opérateur ==. Les objets comparés
doivent tous être des instances de la même classe (et aucun de ses sous-
types), et la classe ne doit pas avoir surchargée l'opérateur ==. Les types
énumérés fonctionne bien avec les instruction switch.
Chaque code associé à une clause case se termine en règle générale par une
instruction break. Les autres moyens valables pour terminer un code associé a
une clause case et d'utiliser les instructions continue, throw ou return.
Utiliser la clause default exécute du code lorsque aucun autre clause case ne
correspond.
L'exemple suivant omet l'instruction break dans une clause case générant ainsi
une erreur:
41
// ERROR: Missing break
case 'CLOSED':
executeClosed();
break;
}
Cependant, Dart ne supporte pas les clause case vide, permettant d’enchaîner
avec le code de la clause suivante:
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
Une clause case peut avoir des variables locales visibles uniquement à
l'intérieur la portée de cette clause.
42
Assert
During development, use an assert statement —
assert(condition, optionalMessage); — to disrupt normal execution if a boolean
condition is false. You can find examples of assert statements throughout this
tour. Here are some more:
assert(urlString.startsWith('https'),
'URL ($urlString) should start with "https".');
When exactly do assertions work? That depends on the tools and framework
you’re using:
In production code, assertions are ignored, and the arguments to assert aren’t
evaluated.
43
Exceptions
Your Dart code can throw and catch exceptions. Exceptions are errors
indicating that something unexpected happened. If the exception isn’t caught,
the isolate that raised the exception is suspended, and typically the isolate and
its program are terminated.
Contrairement à Java, toutes les exceptions de Dart sont des exceptions non
contrôlées. Les méthodes ne déclarent pas quelles exceptions elles pourraient
générer, et vous êtes pas nécessaire pour attraper des exceptions.
Dart fournit les types Exception et Error, ainsi que de nombreux sous-types
prédéfinis. Vous pouvez bien sûr définir vos propres exceptions. Cependant,
les programmes Dart peuvent jeter tout objet non null - pas seulement les
objets Exception et Error - en tant qu'exception.
Throw
Voici un exemple de lancer, ou raising, une exception:
Catch
La capture d’une exception stoppe la propagation (à moins que vous ne
renvoyiez l'exception). Détecter une exception vous donne une chance de la
gérer:
44
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
Pour gérer un code pouvant générer plusieurs types d’exception, vous pouvez:
spécifier plusieurs clauses de capture. La première clause de capture qui
correspond au motif de l'exception sera exécuté. Si la clause capturé ne
spécifiez pas de type, cette clause peut gérer n'importe quel type de motif
d'exception:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
try {
// ···
} on Exception catch (e) {
print('Exception details:\n $e');
} catch (e, s) {
print('Exception details:\n $e');
print('Stack trace:\n $s');
}
void misbehave() {
45
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
print('misbehave() partially handled
${e.runtimeType}.');
rethrow; // Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
Finally
Pour vous assurer que du code est exécuté, qu’une exception soit levée ou
non, utilisez une clause finally. Sinon catch ne correspond à l'exception, la
clause finally sera exécutée. Notez que la clause finally sera exécutée même
si une clause de capture à été exécutée.
try {
breedMoreLlamas();
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); // Handle the exception first.
} finally {
cleanLlamaStalls(); // Then clean up.
}
46
Classes
Dart est un langage orienté objet avec classes et héritage mixin-based.
Chaque objet est une instance d'une classe et toutes les classes descende
de Object. L'héritage mixin-based signifie que même si chaque classe (à
l'exception de Object) a exactement une seule super classe, un corps de
classe peut être réutilisé dans plusieurs hiérarchies de classes.
Utilisez un point (.) pour faire référence à une variable d’instance ou à une
méthode:
// Invoke distanceTo() on p.
num distance = p.distanceTo(Point(4, 4));
Utilisez ?. au lieu de . pour éviter une exception quand l'objet est nul:
47
Le code suivant a le même effet, mais utilise le mot clé new avant le nom du
constructeur:
48
assert(!identical(a, b)); // NOT the same instance!
Note de version: Le mot clé const est devenu facultatif dans un contexte constant dans Dart
2.
Jusqu’ici, vous avez vu comment utiliser les classes. Le reste de cette section
montre comment implémenter des classes
Variables d'instance
Voici comment vous déclarez des variables d'instance:
class Point {
num x; // Declare instance variable x, initially null.
num y; // Declare y, initially null.
num z = 0; // Declare z, initially 0.
}
Toutes les variables d'instance génèrent une méthode getter implicite. Les
variables d'instance non finale génèrent également une méthode setter. Pour
plus de détails, voir Getters et setters .
class Point {
num x;
num y;
}
void main() {
var point = Point();
point.x = 4; // Use the setter method for x.
assert(point.x == 4); // Use the getter method for x.
assert(point.y == null); // Values default to null.
}
49
Si vous initialisez une variable d’instance là où elle est déclarée (au lieu de
l'initialiser via un constructeur ou une méthode), la valeur est définie lorsque
l’instance est créé avant même l'appel du constructeur qui peut donc utiliser
cette variable d'instance.
Constructors
Déclarez un constructeur en créant une fonction portant le même nom que son
classe (plus, éventuellement, un identifiant supplémentaire comme décrit
dans Constructeurs nommés ). La forme la plus courante de constructeur, le
constructeur génératif, crée une nouvelle instance d'une classe:
class Point {
num x, y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
class Point {
num x, y;
50
Les constructeurs ne sont pas hérités
Les classes filles n’héritent pas des constructeurs de leur superclasse. Une
classe fille qui ne déclare aucun constructeur n’a que le constructeur par
défaut (aucun argument, aucun nom).
Constructeurs nommés
Utiliser un constructeur nommé pour implémenter plusieurs constructeurs pour
une classe ou pour plus de clarté:
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
Rappelez-vous que les constructeurs ne sont pas hérités, ce qui signifie qu'un
le constructeur nommé de la superclasse n’est pas hérité par une classe fille.
Si vous voulez que la classe fille soit créée avec un constructeur nommé défini
dans sa superclasse, vous devez implémenter à nouveau ce constructeur
dans la classe fille.
51
Dans l'exemple suivant, le constructeur de la classe Employee appelle le
L'initialisation par liste est pratique lorsqu'on veut définir des variables
d'instance finale. L'exemple suivant initialise 3 variables d'instance finales.
52
Redirection de constructeurs
Parfois, le seul but d’un constructeur est de rediriger vers un autre
constructeur dans la même classe. Le corps du constructeur qui redirige est
alors vide, l’appel du constructeur apparaissant après un signe deux-points (:).
class Point {
num x, y;
Constant constructors
Si votre classe produit des objets qui ne changent jamais, vous pouvez rendre
ces objets constants. Pour ce faire, définissez un constructeur const et
assurez-vous que toutes les variables d'instance sont final.
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
class Logger {
final String name;
53
bool mute = false;
Logger._internal(this.name);
Methods
Les méthodes sont des fonctions associées à une classe ou a une instance de
la classe.
Méthodes d'instance
Les méthodes d'instance sur les objets peuvent accéder aux variables
d'instance et this. La méthode distanceTo() dans l'exemple suivant est un
exemple de méthode d'instance:
import 'dart:math';
class Point {
54
num x, y;
Point(this.x, this.y);
Getters et setters
Les getters et les setters sont des méthodes spéciales qui permettent de lire et
d’écrire les propriétés d’un objet. Rappelons que chaque variable d'instance a
un getter implicite, plus un setter si besoin. Vous pouvez créer des propriétés
supplémentaires en implémentant des getters et des setters, en utilisant les
mots clés get et set.
class Rectangle {
num left, top, width, height;
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
Avec les getters et les setters, vous pouvez commencer par utiliser les
variables d'instance, puis plus tard y accéder en définissant des méthodes, le
tout sans changer le code client.
55
Méthodes abstraites
Les méthodes d’instance, les getter et setter peuvent être abstraites. Elles
sont déclarées mais leur implémentation est laissée à la charge des classes
qui hérite de leur classe. Les méthodes abstraites ne peuvent exister que dans
des classes abstraites .
Pour rendre une méthode abstraite, utilisez un point-virgule (;) au lieu d'un
corps de méthode ({}):
Classes abstraites
Utilisez le mot clé abstract pour définir un abstract class - Une classe qui ne
peut pas être instancié. Les classes abstraites sont utiles pour définir
interfaces, souvent avec une certaine implémentation. Si vous voulez que la
classe abstraite semble instanciable, définissez un constructeur de fabrique.
Interfaces implicites
Chaque classe définit implicitement une interface contenant toute les variables
d'instance. et toutes les interfaces implémentées. Si vous voulez créer une
56
classe A qui supporte l’API de la classe B sans hériter de l'implémentation de
B, la classe A doit implémenter l’interface B.
Une classe implémente une ou plusieurs interfaces en les déclarant dans une
clause implements, puis en fournissant les API requises par l'interfaces. Par
exemple:
// In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
Héritage de classe
Utilisez extends pour créer une sous-classe, et super pour faire référence à la
superclasse:
class Television {
void turnOn() {
_illuminateDisplay();
57
_activateIrSensor();
}
// ···
}
Pour être certains que restreindre le type d’un paramètre de méthode ou d’une
variable d’instance dans le code est type safe, vous pouvez utiliser le mot
clé covariant.
< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
58
– % >>
Remarque: Vous avez peut-être remarqué que !=n'est pas un opérateur que
l'on peut surcharger. L'expression e1 != e2est juste un raccourci syntaxique
pour !(e1 == e2).
class Vector {
final int x, y;
Vector(this.x, this.y);
void main() {
final v = Vector(2, 3);
final w = Vector(2, 2);
noSuchMethod()
Détecter ou réagir lorsque le code tente d’utiliser une méthode non existante
ou variable d'instance non définie, vous pouvez surcharger noSuchMethod():
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
@override
void noSuchMethod(Invocation invocation) {
59
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
Utilisation d'enums
Déclarer un type énuméré en utilisant le mot clé enum:
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
Vous pouvez utiliser des enums dans instructions switch , et vous recevrez un
avertissement si vous ne gérez pas toutes les valeurs de l’enum:
60
var aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
Pour utiliser un mixin. Utilisez le mot clé with suivi d'un ou plusieurs noms de
mixin. L'exemple suivant montre deux classes qui utilisent mixins:
Pour implémenter un mixin, créez une classe qui étend Object et ne déclare
aucun constructeur. A moins que vous ne vouliez que votre mixin soit utilisable
61
comme classe ordinaire, Utilisez le mot clé mixin au lieu de class. Par
exemple:
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
Pour spécifier que seuls certains types peuvent utiliser le mixin - par exemple,
afin que votre mixin puisse invoquer une méthode qu’elle ne définit pas -
utilisez onpour spécifier la superclasse requise:
Version note:Le support du mot clé mixin a été introduit dans Dart 2.1. Les versions
précédentes utilisent abstract class à la place. Pour plus d’informations sur les
modifications de mixin 2.1, voir la Dart SDK changelog et spécification de mixin 2.1.
Variables statiques
Les variables statiques (variables de classe) sont utiles pour les états et les
classes constantes:
class Queue {
static const initialCapacity = 16;
// ···
}
62
void main() {
assert(Queue.initialCapacity == 16);
}
Méthodes statiques
Les méthodes statiques (méthodes de classe) ne fonctionnent pas sur une
instance particulière, et donc n'ont pas accès à this. Par exemple:
import 'dart:math';
class Point {
num x, y;
Point(this.x, this.y);
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
63
Generics
Si vous consultez la documentation de l'API concernant les tableaux simples
et donc le type List, vous verrez que le le type est en fait List<E>. La notation
<...> indique que la List est générique (ou utilise un type paramétrée) type—a
type that has formal type parameters. By convention, most type variables have
single-letter names, such as E, T, S, K, and V.
Si vous souhaitez qu'une liste ne contienne que des chaînes, vous pouvez le
déclarer comme List<String>(lisez cela comme "liste de chaîne"). De cette
façon vous, vos collègues programmeurs et vos outils peuvent détecter que
l’attribution d’autre chose qu'une chaîne à la liste est probablement une erreur.
Voici un exemple:
Vous découvrez que vous voulez une version spécifique pour les chaînes de
caractère de cette interface, alors vous créez une autre interface:
64
}
Plus tard, vous décidez que vous voulez une version spécifique de l'interface
pour les entiers… Vous commencer où nous voulons en venir ?
Les types génériques peuvent vous éviter de créer toutes ces interfaces. Au
lieu de cela, vous pouvez créer une interface unique prenant un paramètre de
type:
Dans ce code, T est le type de remplaçant. C’est un espace réservé que vous
pouvez penser à un type qu'un développeur définira plus tard.
Le code suivant crée une carte qui a des clés entières et des valeurs de type
Vue:
Spécifier un type que ne soit base sur SomeBaseClass génère une erreur.
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
Ici, le paramètre de type générique sur first (<T>) vous permet d'utiliser
l'argument de type T à plusieurs endroits:
Pour plus d'informations sur les génériques, voir Utiliser des méthodes
génériques.
Bibliothèques et visibilité
Les directives import et library peuvent vous aider à créer un code modulaire
et partageable. Les bibliothèques fournissent non seulement des API, mais
sont une unités de confidentialité: les identifiants commençant par un trait de
soulignement (_) sont visibles uniquement à l'intérieur de la
bibliothèque. Chaque application Dart est une bibliothèque même s'il n'utilise
pas de directive library.
Using libraries
Utiliser importpour spécifier comment un espace de noms d'une bibliothèque
est utilisé dans une autre bibliothèque.
import 'dart:html';
Le seul argument requis pour import est une URI spécifiant la bibliothèque.
Pour les bibliothèques intégrées, l’URI commence par le schéma dart:. Pour
67
les autres bibliothèques, vous pouvez utiliser le chemin de la librairie ou
utiliser le schéma du package:. Le schéma du package: spécifie les
bibliothèques fournies par un paquet gestionnaire tel que l'outil "pub". Par
exemple:
import 'package:test/test.dart';
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
68
Pour effectuer des tests A / B, essayez implémentations alternatives
d'un algorithme, par exemple.
Pour charger des fonctionnalités rarement utilisées, telles que des
écrans et des boîtes de dialogue en option.
Only dart2js supports deferred loading. Flutter, the Dart VM, and dartdevc don’t support
deferred loading. For more information, see issue #33118 and issue #27776.
Dans le code précédent, le mot clé await suspend l'exécution jusqu'à ce que la
bibliothèque soit chargée. Pour plus d'informations sur async et await,
voir support asynchrone .
Tenez compte des points suivants lorsque vous utilisez le chargement différé:
Implémentation de librairies
Voir Créer des packages de bibliothèque pour obtenir des conseils sur la
manière de mettre en œuvre un package de bibliothèque, notamment:
69
Comment organiser le code source de la bibliothèque.
Comment utiliser la directive export
Quand utiliser la directive part
Quand utiliser la directive library
Asynchronisme
Les bibliothèques Dart regorgent de fonctions qui retournent des
objets Future ou Stream. Ces fonctions sont asynchrones : ils reviennent
après l'installation une opération qui peut prendre beaucoup de temps (comme
I / O), sans attendre que cette opération soit terminée.
Le code qui utilise async and awaitest asynchrone, mais cela ressemble
beaucoup à du code synchrone. Par exemple, voici du code qui
utilise await pour attendre le résultat d'une fonction asynchrone:
await lookUpVersion();
Pour utiliser await, le code doit être dans un async function - une fonction
marquée comme async:
Remarque: Bien qu'une fonction asynchrone puisse effectuer des opérations fastidieuses, elle
n’attend pas l’exécution de ces opérations. Au lieu de cela, la fonction asynchrone s'exécute
uniquement jusqu'à ce qu'elle rencontre sa première instruction await (détails ). Ensuite, il
retourne un objet Future, et reprend l’exécution seulement après que l’expression await soit
terminée.
70
Utiliser try, catch, et finallypour gérer les erreurs et le nettoyage dans le code
qui utilise await:
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
Vous pouvez utiliser awaitplusieurs fois dans une fonction asynchrone. Par
exemple, le code suivant attend trois fois pour les résultats des fonctions:
Ajouter le mot clé async à une fonction lui fait retourner un Future. Par
exemple, considérons cette fonction synchrone, qui retourne une chaîne:
71
Notez que le corps de la fonction n’a pas besoin d’utiliser l’API Future. Dart
crée l'objet Future si nécessaire.
Si votre fonction ne renvoie pas de valeur utile, faire lui retourner Future<void>.
Remarque: Avant d'utiliser await for, assurez-vous que cela rend le code plus clair et que
vous voulez vraiment attendre tous les résultats du flux. Par exemple, vous devriez
habituellement ne pas utiliser await forpour les listeners d'événements UI, parce que le
Framework UI envoie des flux infinis d’événements.
72
// ...
}
Generators
Lorsque vous devez produire progressivement une séquence de valeurs,
envisager d'utiliser une fonction générateur . Dart prend en charge de manière
intégrée deux types de fonctions de générateur:
73
Les classes appelables
To allow an instance of your Dart class to be called like a function, implement
the call().
Isolates
La plupart des ordinateurs, même sur les plates-formes mobiles, ont des
processeurs multicœurs. Pour tirer parti de tous ces cœurs, les développeurs
utilisent traditionnellement threads de mémoire partagée s'exécutant
simultanément. Cependant, l'état partagé la concurrence est sujette aux
erreurs et peut conduire à un code compliqué.
Typedefs
Dans Dart, les fonctions sont des objets, tout comme les chaînes et les
nombres sont objets. Un typedef, ou function-type alias, donne à une fonction
un nom que vous pouvez utiliser lors de la déclaration de champs ou faites
des retour. Un typedef conserve les informations de type lorsqu'un type de
fonction est affecté à une variable.
class SortedCollection {
Function compare;
74
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
void main() {
SortedCollection coll = SortedCollection(sort);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
Note:Actuellement, les typedefs sont limités aux types de fonction. Cela pourrait changer.
Parce que les typedefs sont simplement des alias, ils offrent un moyen de
vérifier le type de toute fonction. Par exemple:
75
void main() {
assert(sort is Compare<int>); // True!
}
Metadata
Utilisez les métadonnées pour donner des informations supplémentaires sur
votre code. Dans une métadonnée, l'annotation commence par le caractère @,
suivi soit d'une référence à une constante de compilation (telle que deprecated)
ou un appel à un constructeur constant.
class Television {
/// _Deprecated: Use [turnOn] instead._
@deprecated
void activate() {
turnOn();
}
library todo;
class Todo {
final String who;
final String what;
import 'todo.dart';
Comments
Dart prend en charge les commentaires sur une seule ligne, les commentaires
sur plusieurs lignes et commentaires de la documentation.
void main() {
// TODO: refactor into an AbstractLlamaGreetingFactory?
print('Welcome to my Llama farm!');
}
Commentaires multilignes
Un commentaire multiligne commence par /* et se termine par */. Tout
entre /* and */ est ignoré par le compilateur Dart (à moins que le commentaire
soit un commentaire de documentation; voir la section suivante). Les
commentaires multiligne peuvent nidifier.
void main() {
/*
* This is a lot of work. Consider raising chickens.
Commentaires de la documentation
77
Les commentaires de la documentation sont des commentaires multilignes ou
simples qui commencent avec /// or /**. En utilisez ///sur les lignes
consécutives a le même effet en tant que commentaire doc multi-lignes.
Pour analyser le code Dart et générer une documentation HTML, vous pouvez
utiliser le logiciel SDK. outil de génération de documentation. . Pour un
exemple de la documentation générée, voir la Documentation de l'API Dart.
Pour des conseils sur la façon de structurer vos commentaires,
voir Instructions pour les commentaires Dart Doc.
78
Summary
Cette page résume les fonctionnalités couramment utilisées dans le langage
Dart. Davantage de fonctionnalités seront mises en œuvre, mais nous nous
attendons à ce qu’elles ne cassent pas le code existant. Pour plus
d'informations, voir la Spécification du langage Dartand Dart efficace .
Pour en savoir plus sur les bibliothèques principales de Dart, voir Visite des
bibliothèques Dart.
79
Dart efficace
Contents
Les guides
Comment lire les guides
Glossaire
Résumé de toutes les règles
o Style
o Documentation
o Usage
o Conception
Au cours des dernières années, nous avons écrit une tonne de code Dart et avons beaucoup
appris à propos de ce qui fonctionne bien et de ce qui ne fonctionne pas. Nous partageons cela
avec vous pour que vous puissiez écrire aussi un code cohérent, robuste et rapide. Il y a deux
thèmes généraux:
1. Être cohérent. Lorsque tout devient compliqué et qu'on y comprend plus rien, le
mieux c'est encore d'être consistent. Cet objectif peut vous être utile !
2. Etre concis.Dart a été conçu pour être familier, il hérite donc de la plupart des mêmes
déclarations et expressions que C, Java, JavaScript et d’autres langages. Mais nous
avons créé Dart parce qu’il reste encore beaucoup à faire pour améliorer ce que offre
les langages. Nous avons ajouté de nombreuses fonctionnalités, pour vous aider à
exprimer votre intention le plus simplement et facilement.
S'il y a plusieurs façons de dire quelque chose, vous devriez généralement choisir le
plus concis. Cela ne veut pas dire que vous devriez participer au code golf et entasser
tout un programme dans une seule ligne. Le but est un code qu'il soit économique ,
mais pas dense.
The Dart analyzer has a linter to help you write good, consistent code. If a linter rule exists
that can help you follow a guideline, then the guideline links to that rule. Here’s an example:
For help on enabling linter rules, see the documentation for customizing static analysis.
80
The guides
Nous avons divisé les lignes directrices en quelques pages distinctes pour faciliter la
digestion:
Guide de style- Ce guide définit les règles de mise en page et d'organisation du code,
ou au moins les parties que dartfmt ne gère pas pour vous. Le guide de style spécifie
également comment les identificateurs sont
formatés: camelCase, using_underscores, etc.
Guide de documentation - Ce guide vous dit tout ce que vous avez besoin savoir sur
ce qui se passe à l'intérieur des commentaires. Les commentaires standards et les
commentaires de documentation, les commentaires de code usuels.
Guide d'utilisation - Ce guide vous apprend à tirer le meilleur parti de fonctionnalités
du langage pour implémenter le comportement. Si c’est dans une déclaration ou
expression, c’est couvert ici.
Guide de conception - C’est le guide le plus simple, mais celui avec la plus grande
portée. Il couvre ce que nous avons appris sur la conception API cohérentes et
utilisables pour les bibliothèques. Si c’est dans une signature de type ou déclaration,
cela passe dessus.
A RESPECTER: ces directives décrivent les pratiques qui doivent toujours être
suivies. Il n'y a aucune raison valable de pas suivre ces directives !
NE JAMAIS FAIRE: ces directives sont l'inverse des directives A RESPECTER: des
choses qui ne sont presque jamais bonnes idée.
DE PREFERENCE: ces directives sont des pratiques que vous devriez suivre.
Cependant, là peut-être qu'il existe des circonstances où il est logique de faire
autrement. Assurez-vous juste comprendre toutes les implications avant d'ignorer la
directive lorsque vous le faites.
A EVITER: ces directives sont les choses que vous ne devriez pas faire mais où il
peut y avoir de bonnes raisons à de rares occasions de le faire quand même.
A CONSIDERER: ces directives sont des cas pratiques que vous pourrez suivre si
vous le désirez, selon les circonstances, vos habitudes et votre propre préférence.
Some guidelines describe an exception where the rule does not apply. When listed, the
exceptions may not be exhaustive—you might still need to use your judgement on other cases.
On dirait que la police va frapper à votre porte si vous ne respectez pas ces directives, mais les
choses ne sont pas aussi sombres. La plupart des lignes directrices présentées ici sont du bon
sens et nous sommes tous des gens raisonnables. Le but final est que votre code soit sympa,
lisible et maintenable.
81
Glossary
Pour garder les lignes directrices brèves, nous utilisons quelques termes abrégés pour faire
référence à différents éléments de Dart.
Ordonnancement
82
Mise en forme
Documentation
Commentaires
Commentaires de documentation
Markdown
Writing
PREFER brevity.
AVOID abbreviations and acronyms unless they are obvious.
PREFER using “this” instead of “the” to refer to a member’s instance.
83
Usage
Bibliothèques
Booleans
Les collections
Les fonctions
Les paramètres
Les variables
Les membres
84
DO initialize fields at their declaration when possible.
Les constructeurs
Asynchronisme
Design
Les noms
85
DO follow existing mnemonic conventions when naming type parameters.
Les bibliothèques
AVOID defining a one-member abstract class when a simple function will do.
AVOID defining a class that contains only static members.
AVOID extending a class that isn’t intended to be subclassed.
DO document if your class supports being extended.
AVOID implementing a class that isn’t intended to be an interface.
DO document if your class supports being used as an interface.
DO use mixin to define a mixin type.
AVOID mixing in a type that isn’t intended to be a mixin.
Les constructeurs
Members
Les types
PREFER type annotating public fields and top-level variables if the type isn’t obvious.
CONSIDER type annotating private fields and top-level variables if the type isn’t obvious.
AVOID type annotating initialized local variables.
AVOID annotating inferred parameter types on function expressions.
AVOID redundant type arguments on generic invocations.
DO annotate when Dart infers the wrong type.
PREFER annotating with dynamic instead of letting inference fail.
PREFER signatures in function type annotations.
DON’T specify a return type for a setter.
DON’T use the legacy typedef syntax.
PREFER inline function types over typedefs.
CONSIDER using function type syntax for parameters.
DO annotate with Object instead of dynamic to indicate any object is allowed.
DO use Future<void> as the return type of asynchronous members that do not produce
values.
AVOID using FutureOr<T> as a return type.
Les paramètres
86
AVOID positional boolean parameters.
AVOID optional positional parameters if the user may want to omit earlier parameters.
AVOID mandatory parameters that accept a special “no argument” value.
DO use inclusive start and exclusive end parameters to accept a range.
Égalité
87
A surprisingly important part of good code is good style. Consistent naming, ordering, and
formatting helps code that is the same lookthe same. It takes advantage of the powerful
pattern-matching hardware most of us have in our ocular systems. If we use a consistent style
across the entire Dart ecosystem, it makes it easier for all of us to learn from and contribute to
each others’ code.
Identifiers
Identifiers come in three flavors in Dart.
UpperCamelCase names capitalize the first letter of each word, including the first.
lowerCamelCase names capitalize the first letter of each word, except the first which
is always lowercase, even if it’s an acronym.
lowercase_with_underscores use only lowercase letters, even for acronyms, and
separate words with _.
Classes, enums, typedefs, and type parameters should capitalize the first letter of each word
(including the first word), and use no separators.
class Foo {
const Foo([arg]);
}
@Foo(anArg)
class A { ... }
@Foo()
class B { ... }
If the annotation class’s constructor takes no parameters, you might want to create a
separate lowerCamelCase constant for it.
88
const foo = Foo();
@foo
class C { ... }
Some file systems are not case-sensitive, so many projects require filenames to be all
lowercase. Using a separating character allows names to still be readable in that form. Using
underscores as the separator ensures that the name is still a valid Dart identifier, which may be
helpful if the language later supports symbolic imports.
library peg_parser.source_scanner;
import 'file_system.dart';
import 'slider_menu.dart';
library pegparser.SourceScanner;
import 'file-system.dart';
import 'SliderMenu.dart';
Remarque: This guideline specifies how to name a library if you choose to name it. It is fine
to omit the library directive in a file if you want.
89
A RESPECTER: nommez les autres
identifiants à l'aide de lowerCamelCase.
Linter rule: non_constant_identifier_names
Class members, top-level definitions, variables, parameters, and named parameters should
capitalize the first letter of each word exceptthe first word, and use no separators.
var item;
HttpRequest httpRequest;
In new code, use lowerCamelCase for constant variables, including enum values.
const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');
class Dice {
static final numberGenerator = Random();
}
const PI = 3.14;
const DefaultTimeout = 1000;
final URL_SCHEME = RegExp('^([a-z]+):');
class Dice {
static final NUMBER_GENERATOR = Random();
}
You may use SCREAMING_CAPS for consistency with existing code, as in the following cases:
90
Remarque: We initially used Java’s SCREAMING_CAPS style for constants. We changed for a
few reasons:
SCREAMING_CAPS looks bad for many cases, particularly enum values for things like CSS
colors.
Constants are often changed to final non-const variables, which would necessitate a name
change.
The values property automatically defined on an enum type is const and lowercase.
To avoid this, acronyms and abbreviations are capitalized like regular words, except for two-
letter acronyms. (Two-letter abbreviationslike ID and Mr. are still capitalized like words.)
HttpConnectionInfo
uiHandler
IOStream
HttpRequest
Id
DB
HTTPConnection
UiHandler
IoStream
HTTPRequest
ID
Db
There is no concept of “private” for local variables, parameters, or library prefixes. When one
of those has a name that starts with an underscore, it sends a confusing signal to the reader. To
avoid that, don’t use leading underscores in those names.
91
Exception: An unused parameter can be named _, __, ___, etc. This happens in things like
callbacks where you are passed a value but you don’t need to use it. Giving it a name that
consists solely of underscores is the idiomatic way to indicate the value isn’t used.
defaultTimeout
kDefaultTimeout
Ordering
To keep the preamble of your file tidy, we have a prescribed order that directives should
appear in. Each “section” should be separated by a blank line.
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
92
import 'util.dart';
If you have a number of “package:” imports for your own package along with other external
packages, place yours in a separate section after the external ones.
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:my_package/util.dart';
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';
import 'src/error.dart';
export 'src/error.dart';
import 'src/foo_bar.dart';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'foo.dart';
import 'foo/foo.dart';
import 'package:foo/foo.dart';
93
import 'package:bar/bar.dart';
import 'foo/foo.dart';
import 'foo.dart';
Formatting
Like many languages, Dart ignores whitespace. However, humans don’t. Having a consistent
whitespace style helps ensure that human readers see code the same way the compiler does.
The remaining formatting guidelines are for the few things dartfmt cannot fix for you.
When that happens, reorganize or simplify your code. Consider shortening a local variable
name or hoisting out an expression into a new local variable. In other words, make the same
kinds of modifications that you’d make if you were formatting the code by hand and trying to
make it more readable. Think of dartfmt as a partnership where you work together, sometimes
iteratively, to produce beautiful code.
Readability studies show that long lines of text are harder to read because your eye has to
travel farther when moving to the beginning of the next line. This is why newspapers and
magazines use multiple columns of text.
If you really find yourself wanting lines longer than 80 characters, our experience is that your
code is likely too verbose and could be a little more compact. The main offender is
94
usually VeryLongCamelCaseClassNames. Ask yourself, “Does each word in that type name
tell me something critical or prevent a name collision?” If not, consider omitting it.
Note that dartfmt does 99% of this for you, but the last 1% is you. It does not split long string
literals to fit in 80 columns, so you have to do that manually.
Exception: When a URI or file path occurs in a comment or string (usually in an import or
export), it may remain whole even if it causes the line to go over 80 characters. This makes it
easier to search source files for a path.
Exception: Multi-line strings can contain lines longer than 80 characters because newlines
are significant inside the string and splitting the lines into shorter ones can alter the program.
if (isWeekDay) {
print('Bike to work!');
} else {
print('Go dancing or read a book!');
}
Exception: When you have an if statement with no else clause and the whole if statement
fits on one line, you can omit the braces if you prefer:
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;
⟨ Overview
95
Effective Dart:
Documentation
Contents
Comments
o A RESPECTER: formatez les commentaires comme des phrases.
o DON’T use block comments for documentation.
Doc comments
o DO use /// doc comments to document members and types.
o PREFER writing doc comments for public APIs.
o CONSIDER writing a library-level doc comment.
o CONSIDER writing doc comments for private APIs.
o A RESPECTER: commencez les commentaires de documentation
avec un résumé en une phrase.
o A RESPECTER: séparez la première phrase d'un commentaire
de documentation du reste du commentaire
o AVOID redundancy with the surrounding context.
o PREFER starting function or method comments with third-person
verbs.
o PREFER starting variable, getter, or setter comments with noun
phrases.
o PREFER starting library or type comments with noun phrases.
o CONSIDER including code samples in doc comments.
o DO use square brackets in doc comments to refer to in-scope
identifiers.
o DO use prose to explain parameters, return values, and
exceptions.
o DO put doc comments before metadata annotations.
Markdown
o AVOID using markdown excessively.
o AVOID using HTML for formatting.
o PREFER backtick fences for code blocks.
Writing
o PREFER brevity.
o AVOID abbreviations and acronyms unless they are obvious.
o PREFER using “this” instead of “the” to refer to a member’s
instance.
It’s easy to think your code is obvious today without realizing how much you
rely on context already in your head. People new to your code, and even your
forgetful future self won’t have that context. A concise, accurate comment only
takes a few seconds to write but can save one of those people hours of time.
96
We all know code should be self-documenting and not all comments are
helpful. But the reality is that most of us don’t write as many comments as we
should. It’s like exercise: you technically can do too much, but it’s a lot more
likely that you’re doing too little. Try to step it up.
commentaires
The following tips apply to comments that you don’t want included in the
generated documentation.
Capitalize the first word unless it’s a case-sensitive identifier. End it with a
period (or “!” or “?”, I suppose). This is true for all comments: doc comments,
inline stuff, even TODOs. Even if it’s a sentence fragment.
You can use a block comment (/* ... */) to temporarily comment out a
section of code, but all other comments should use //.
Doc comments
Doc comments are especially handy because dartdoc parses them and
generates beautiful doc pages from them. A doc comment is any comment
that appears before a declaration and uses the special /// syntax that dartdoc
looks for.
97
A RESPECTER: utilisez /// doc
comments to document members and
types.
Linter rule: slash_for_doc_comments
If you stumble onto code that still uses the JavaDoc style, consider cleaning it
up.
You don’t have to document every single library, top-level variable, type, and
member, but you should document most of them.
98
A single-sentence summary of what the library is for.
Explanations of terminology used throughout the library.
A couple of complete code samples that walk through using the API.
Links to the most important or most commonly used classes and
functions.
Links to external references on the domain the library is concerned with.
99
A RESPECTER: séparez la première
phrase d'un commentaire de
documentation du reste du
commentaire
Add a blank line after the first sentence to split it out into its own paragraph. If
more than a single sentence of explanation is useful, put the rest in later
paragraphs.
This helps you write a tight first sentence that summarizes the documentation.
Also, tools like Dartdoc use the first paragraph as a short summary in places
like lists of classes and members.
100
/// Sets the tooltip to [lines], which should have been
word wrapped using
/// the current font.
void tooltip(List<String> lines) {
...
}
}
class RadioButtonWidget extends Widget {
/// Sets the tooltip for this radio button widget to the
list of strings in
/// [lines].
void tooltip(List<String> lines) {
...
}
}
101
Avoid having a doc comment on both the setter and the getter, as DartDoc will
show only one (the one on the getter.)
If you surround things like variable, method, or type names in square brackets,
then dartdoc looks up the name and links to the relevant API docs.
Parentheses are optional, but can make it clearer when you’re referring to a
method or constructor.
To link to a member of a specific class, use the class name and member
name, separated by a dot:
The dot syntax can also be used to refer to named constructors. For the
unnamed constructor, put parentheses after the class name:
The convention in Dart is to integrate that into the description of the method
and highlight parameters using square brackets.
Markdown
You are allowed to use most markdown formatting in your doc comments and
dartdoc will process it accordingly using the markdown package.
There are tons of guides out there already to introduce you to Markdown. Its
universal popularity is why we chose it. Here’s just a quick example to give you
a flavor of what’s supported:
104
/// The code language (for syntax highlighting) defaults
to Dart. You can
/// specify it by putting the name of the language after
the opening backticks:
///
/// ```html
/// <h1>HTML is magical!</h1>
/// ```
///
/// Links can be:
///
/// * http://www.just-a-bare-url.com
/// * [with the URL inline](http://google.com)
/// * [or separated out][ref link]
///
/// [ref link]: http://google.com
///
/// # A Header
///
/// ## A subheader
///
/// ### A subsubheader
///
/// #### If you need this many levels of headers, you're
doing it wrong
105
indentation is already meaningful or when the code block itself contains
indented code.
The backtick syntax avoids those indentation woes, lets you indicate the
code’s language, and is consistent with using backticks for inline code.
Writing
We think of ourselves as programmers, but most of the characters in a source
file are intended primarily for humans to read. English is the language we code
in to modify the brains of our coworkers. As for any programming language, it’s
worth putting effort into improving your proficiency.
This section lists a few guidelines for our docs. You can learn more about best
practices for technical writing, in general, from articles such as Technical
writing style.
PREFER brevity.
Be clear and precise, but also terse.
class Box {
/// The value this wraps.
var _value;
107
A tour of the core libraries
Contents
This page shows you how to use the major features in Dart’s core libraries. It’s
just an overview, and by no means comprehensive. Whenever you need more
details about a class, consult the Dart API reference.
dart:core
108
Types intégrés, collections et autres fonctionnalités principales. Cette
bibliothèque est automatiquement importée dans chaque programme
Dart.
dart:async
dart:math
dart:convert
dart:html
dart:io
I/O for programs that can use the Dart VM, including Flutter apps,
servers, and command-line scripts.
This page is just an overview; it covers only a few dart:* libraries and no third-
party libraries.
Other places to find library information are the Pub site et le Dart web
developer library guide. You can find API documentation for all dart:* libraries
in the API Dart ou, si vous utilisez Flutter, la API Flutter.
Astuce DartPad: Vous pouvez jouer avec le code de cette page en le copiant dans un
fichier DartPad.
109
Ecrire sur la console
La méthode globale print() prend un seul argument (de n'importe quel objet)
et affiche la valeur de chaîne de cet objet (telle que renvoyée par toString())
dans la console.
print(anObject);
print('I drink $tea.');
Pour plus d’informations sur les chaînes de base et toString(), voir Les
chaînes de caractères dans le tour de langue.
Numbers
La bibliothèque dart:core définit les classes num, int et double, qui offrent des
méthodes de base pour travailler avec des nombres.
assert(int.parse('42') == 42);
assert(int.parse('0x42') == 66);
assert(double.parse('0.50') == 0.5);
assert(num.parse('42') is int);
assert(num.parse('0x42') is int);
assert(num.parse('0.50') is double);
110
// Specify the number of digits after the decimal.
assert(123.456.toStringAsFixed(2) == '123.46');
111
exemple, le symbole de la clé de sol ('\u{1D11E}') est composé deux unités de
code.
// Grab a substring.
assert('Never odd or even'.substring(6, 9) == 'odd');
// Convert to uppercase.
assert('structured web apps'.toUpperCase() ==
'STRUCTURED WEB APPS');
// Convert to lowercase.
assert('STRUCTURED WEB APPS'.toLowerCase() ==
'structured web apps');
Remarque: Ces méthodes ne fonctionnent pas pour toutes les langues. Par
exemple, le turc l’alphabet sans points I is converted incorrectly.
// Trim a string.
assert(' hello '.trim() == 'hello');
Building a string
To programmatically generate a string, you can use StringBuffer. A
StringBuffer doesn’t generate a new String object until toString() is called.
The writeAll() method has an optional second parameter that lets you specify
a separator—in this case, a space.
var sb = StringBuffer();
sb
..write('Use a StringBuffer for ')
..writeAll(['efficient', 'string', 'creation'], ' ')
..write('.');
assert(fullString ==
'Use a StringBuffer for efficient string creation.');
Regular expressions
113
The RegExp class provides the same capabilities as JavaScript regular
expressions. Use regular expressions for efficient searching and pattern
matching of strings.
You can work directly with the RegExp class, too. The Match class provides
access to a regular expression match.
Plus d'information
Refer to the String API reference for a full list of methods. Also see the API
reference for StringBuffer, Pattern, RegExp, and Match.
Collections
Dart ships with a core collections API, which includes classes for lists, sets,
and maps.
Les listes
114
As the language tour shows, you can use literals to create and initialize lists.
Alternatively, use one of the List constructors. The List class also defines
several methods for adding items to and removing items from lists.
// Add to a list.
fruits.add('kiwis');
Sort a list using the sort() method. You can provide a sorting function that
compares two objects. This sorting function must return < 0 for smaller, 0 for
the same, and > 0 for bigger. The following example uses compareTo(), which
is defined by Comparable and implemented by String.
// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
115
assert(fruits[0] == 'apples');
Lists are parameterized types, so you can specify the type that a list should
contain:
fruits.add('apples');
var fruit = fruits[0];
assert(fruit is String);
fruits.add(5); // Error: 'int' can't be assigned to
'String'
Sets
A set in Dart is an unordered collection of unique items. Because a set is
unordered, you can’t get a set’s items by index (position).
Use contains() and containsAll() to check whether one or more objects are in
a set:
116
var ingredients = Set();
ingredients.addAll(['gold', 'titanium', 'xenon']);
Maps
A map, commonly known as a dictionary or hash, is an unordered collection of
key-value pairs. Maps associate a key to some value for easy retrieval. Unlike
in JavaScript, Dart objects are not maps.
You can declare a map using a terse literal syntax, or you can use a traditional
constructor:
You add, get, and set map items using the bracket syntax. Use remove() to
remove a key and its value from a map.
117
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));
You can retrieve all the values or all the keys from a map:
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
assert(keys.length == 3);
assert(Set.from(keys).contains('Oahu'));
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu']
};
assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));
Use the putIfAbsent() method when you want to assign a value to a key if and
only if the key does not already exist in a map. You must provide a function
that returns the value.
118
Common collection methods
List, Set, and Map share common functionality found in many collections.
Some of this common functionality is defined by the Iterable class, which List
and Set implement.
Remarque: Although Map doesn’t implement Iterable, you can get Iterables
from it using the Map keys and values properties.
Use isEmpty or isNotEmpty to check whether a list, set, or map has items:
To apply a function to each item in a list, set, or map, you can use forEach():
When you invoke forEach() on a map, your function must take two arguments
(the key and value):
hawaiianBeaches.forEach((k, v) {
print('I want to visit $k and swim at $v');
// I want to visit Oahu and swim at
// [Waikiki, Kailua, Waimanalo], etc.
});
Iterables provide the map() method, which gives you all the results in a single
object:
Note: The object returned by map() is an Iterable that’s lazily evaluated: your
function isn’t called until you ask for an item from the returned object.
var loudTeas =
119
teas.map((tea) => tea.toUpperCase()).toList();
Use Iterable’s where() method to get all the items that match a condition. Use
Iterable’s any() and every() methods to check whether some or all items match
a condition.
For a full list of methods, refer to the Iterable API reference, as well as those
for List, Set, and Map.
URIs
The Uri class provides functions to encode and decode strings for use in URIs
(which you might know as URLs). These functions handle characters that are
special for URIs, such as & and =. The Uri class also parses and exposes the
components of a URI—host, port, scheme, and so on.
120
var encoded = Uri.encodeFull(uri);
assert(encoded ==
'http://example.org/api?foo=some%20message');
Notice how only the space between some and message was encoded.
'http%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message');
Parsing URIs
If you have a Uri object or a URI string, you can get its parts using Uri fields
such as path. To create a Uri from a string, use the parse()static method:
var uri =
Uri.parse('http://example.org:8080/foo/bar#frag');
assert(uri.scheme == 'http');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'http://example.org:8080');
See the Uri API reference for more URI components that you can get.
Building URIs
121
You can build up a URI from individual parts using the Uri() constructor:
// 1/1/2000, UTC
var y2k = DateTime.utc(2000);
assert(y2k.millisecondsSinceEpoch == 946684800000);
// 1/1/1970, UTC
var unixEpoch = DateTime.utc(1970);
assert(unixEpoch.millisecondsSinceEpoch == 0);
122
Use the Duration class to calculate the difference between two dates and to
shift a date forward or backward:
// Subtract 30 days.
var december2000 = y2001.subtract(Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);
For a full list of methods, refer to the API reference for DateTime and Duration.
Utility classes
The core library contains various utility classes, useful for sorting, mapping
values, and iterating.
Comparing objects
Implement the Comparable interface to indicate that an object can be
compared to another object, usually for sorting. The compareTo()method
returns < 0 for smaller, 0 for the same, and > 0 for bigger.
@override
int compareTo(Line other) => length - other.length;
}
void main() {
var short = const Line(1);
123
var long = const Line(100);
assert(short.compareTo(long) < 0);
}
class Person {
final String firstName, lastName;
Person(this.firstName, this.lastName);
void main() {
var p1 = Person('Bob', 'Smith');
var p2 = Person('Bob', 'Smith');
var p3 = 'not a person';
assert(p1.hashCode == p2.hashCode);
assert(p1 == p2);
assert(p1 != p3);
}
124
Iteration
The Iterable and Iterator classes support for-in loops. Extend (if possible) or
implement Iterable whenever you create a class that can provide Iterators for
use in for-in loops. Implement Iterator to define the actual iteration ability.
class Process {
// Represents a process...
}
void main() {
// Iterable objects can be used with for-in.
for (var process in Processes()) {
// Do something with the process.
}
}
Les exceptions
The Dart core library defines many common exceptions and errors. Exceptions
are considered conditions that you can plan ahead for and catch. Errors are
conditions that you don’t expect or plan for.
NoSuchMethodError
ArgumentError
125
Can be thrown by a method that encounters an unexpected argument.
const FooException([this.msg]);
@override
String toString() => msg ?? 'FooException';
}
For more information, see Exceptions (in the language tour) and the Exception
API reference.
dart:async - asynchronous
programming
Asynchronous programming often uses callback functions, but Dart provides
alternatives: Future and Stream objects. A Future is like a promise for a result
to be provided sometime in the future. A Stream is a way to get a sequence of
values, such as events. Future, Stream, and more are in the dart:async library
(API reference).
Note: You don’t always need to use the Future or Stream APIs directly. The
Dart language supports asynchronous coding using keywords such
as async and await. See Asynchronisme in the language tour for details.
The dart:async library works in both web apps and command-line apps. To
use it, import dart:async:
import 'dart:async';
Note de version: As of Dart 2.1, you don’t need to import dart:async to use the Future and
Stream APIs, because dart:core exports those classes.
Future
126
Future objects appear throughout the Dart libraries, often as the object
returned by an asynchronous method. When a future completes, its value is
ready to use.
Using await
Before you directly use the Future API, consider using await instead. Code that
uses await expressions can be easier to understand than code that uses the
Future API.
runUsingFuture() {
// ...
findEntryPoint().then((entryPoint) {
return runExecutable(entryPoint, args);
}).then(flushThenExit);
}
The equivalent code with await expressions looks more like synchronous
code:
runUsingAsyncAwait() async {
// ...
var entryPoint = await findEntryPoint();
var exitCode = await runExecutable(entryPoint, args);
await flushThenExit(exitCode);
}
Important: Async functions return Futures. If you don’t want your function to
return a future, then use a different solution. For example, you might call an
async function from your function.
127
For more information on using await and related Dart language features,
see Asynchronisme .
Basic usage
You can use then() to schedule code that runs when the future completes. For
example, HttpRequest.getString() returns a Future, since HTTP requests can
take a while. Using then() lets you run some code when that Future has
completed and the promised string value is available:
HttpRequest.getString(url).then((String result) {
print(result);
});
Use catchError() to handle any errors or exceptions that a Future object might
throw.
HttpRequest.getString(url).then((String result) {
print(result);
}).catchError((e) {
// Handle or ignore the error.
});
128
});
1. costlyQuery()
2. expensiveWork()
3. lengthyComputation()
try {
final value = await costlyQuery(url);
await expensiveWork(value);
await lengthyComputation();
print('Done!');
} catch (e) {
/* Handle exception... */
}
await Future.wait([
deleteLotsOfFiles(),
copyLotsOfFiles(),
checksumLotsOfOtherFiles(),
]);
print('Done with all the long steps!');
Stream
Stream objects appear throughout Dart APIs, representing sequences of data.
For example, HTML events such as button clicks are delivered using streams.
You can also read a file as a stream.
Important: Before using await for, make sure that it makes the code clearer
and that you really do want to wait for all of the stream’s results. For example,
you usually should not use await for for DOM event listeners, because the
DOM sends endless streams of events. If you use await for to register two
DOM event listeners in a row, then the second kind of event is never handled.
130
For more information on using await and related Dart language features,
see Asynchronisme .
If you care about only one event, you can get it using a property such
as first, last, or single. To test the event before handling it, use a method
such as firstWhere(), lastWhere(), or singleWhere().
If you care about a subset of events, you can use methods such
as skip(), skipWhile(), take(), takeWhile(), and where().
This example uses two transformers. First it uses utf8.decoder to transform the
stream of integers into a stream of strings. Then it uses a LineSplitter to
transform the stream of strings into a stream of separate lines. These
transformers are from the dart:convert library (see the dart:convert section).
If you use an asynchronous for loop, then use try-catch to handle errors. Code
that executes after the stream is closed goes after the asynchronous for loop.
131
Future readFileAwaitFor() async {
var config = File('config.txt');
Stream<List<int>> inputStream = config.openRead();
inputStream
.transform(utf8.decoder)
.transform(LineSplitter())
.listen((String line) {
print('Got ${line.length} characters from stream');
}, onDone: () {
print('file is now closed');
}, onError: (e) {
print(e);
});
Plus d'information
For some examples of using Future and Stream in command-line apps, see
the Visite de dart:io. Also see these articles and tutorials:
132
dart:math - math and random
The dart:math library (API reference) provides common functionality such as
sine and cosine, maximum and minimum, and constants such as pi and e.
Most of the functionality in the Math library is implemented as top-level
functions.
import 'dart:math';
Trigonometry
The Math library provides basic trigonometric functions:
// Cosine
assert(cos(pi) == -1.0);
// Sine
var degrees = 30;
var radians = degrees * (pi / 180);
// radians is now 0.52359.
var sinOf30degrees = sin(radians);
// sin 30° = 0.5
assert((sinOf30degrees - 0.5).abs() < 0.01);
Math constants
Find your favorite constants—pi, e, and more—in the Math library:
133
Random numbers
Generate random numbers with the Random class. You can optionally provide
a seed to the Random constructor.
Plus d'information
Refer to the Math API reference for a full list of methods. Also see the API
reference for num, int, and double.
The dart:convert library works in both web apps and command-line apps. To
use it, import dart:convert.
import 'dart:convert';
134
{"score": 40},
{"score": 80}
]
''';
var scores = [
{'score': 40},
{'score': 80},
{'score': 100, 'overtime': true, 'special_guest': null}
];
Only objects of type int, double, String, bool, null, List, or Map (with string
keys) are directly encodable into JSON. List and Map objects are encoded
recursively.
You have two options for encoding objects that aren’t directly encodable. The
first is to invoke encode() with a second argument: a function that returns an
object that is directly encodable. Your second option is to omit the second
argument, in which case the encoder calls the object’s toJson() method.
For more examples and links to JSON-related packages, see JSON Support.
List<int> utf8Bytes = [
0xc3, 0x8e, 0xc3, 0xb1, 0xc5, 0xa3, 0xc3, 0xa9,
135
0x72, 0xc3, 0xb1, 0xc3, 0xa5, 0xc5, 0xa3, 0xc3,
0xae, 0xc3, 0xb6, 0xc3, 0xb1, 0xc3, 0xa5, 0xc4,
0xbc, 0xc3, 0xae, 0xc5, 0xbe, 0xc3, 0xa5, 0xc5,
0xa3, 0xc3, 0xae, 0xe1, 0xbb, 0x9d, 0xc3, 0xb1
];
assert(funnyWord == 'Îñţérñåţîöñåļîžåţîờñ');
var lines =
utf8.decoder.bind(inputStream).transform(LineSplitter());
try {
await for (var line in lines) {
print('Got ${line.length} characters from stream');
}
print('file is now closed');
} catch (e) {
print(e);
}
assert(encoded.length == utf8Bytes.length);
for (int i = 0; i < encoded.length; i++) {
assert(encoded[i] == utf8Bytes[i]);
}
Other functionality
The dart:convert library also has converters for ASCII and ISO-8859-1
(Latin1). For details, see the API reference for the dart:convert library.
136
Other common uses of dart:html are manipulating styles (CSS), getting data
using HTTP requests, and exchanging data usingWebSockets. HTML5 (and
dart:html) has many additional APIs that this section doesn’t cover. Only web
apps can use dart:html, not command-line apps.
Note: For a higher level approach to web app UIs, use a web framework such
as AngularDart.
import 'dart:html';
A Window object represents the actual window of the web browser. Each
Window has a Document object, which points to the document that’s currently
loaded. The Window object also has accessors to various APIs such as
IndexedDB (for storing data), requestAnimationFrame (for animations), and
more. In tabbed browsers, each tab has its own Window object.
With the Document object, you can create and manipulate Element objects
within the document. Note that the document itself is an element and can be
manipulated.
The DOM models a tree of Nodes. These nodes are often elements, but they
can also be attributes, text, comments, and other DOM types. Except for the
root node, which has no parent, each node in the DOM has one parent and
might have many children.
Finding elements
To manipulate an element, you first need an object that represents it. You can
get this object using a query.
The querySelector() function returns the first element that matches the
selector, while querySelectorAll()returns a collection of elements that match
the selector.
137
// Find an element by id (an-id).
Element elem1 = querySelector('#an-id');
Manipulating elements
You can use properties to change the state of an element. Node and its
subtype Element define the properties that all elements have. For example, all
elements have classes, hidden, id, style, and title properties that you can use
to set state. Subclasses of Element define additional properties, such as
the href property of AnchorElement.
This <a> tag specifies an element with an href attribute and a text node
(accessible via a text property) that contains the string “linktext”. To change
the URL that the link goes to, you can use AnchorElement’s href property:
Often you need to set properties on multiple elements. For example, the
following code sets the hidden property of all elements that have a class of
“mac”, “win”, or “linux”. Setting the hidden property to true has the same effect
as adding display:none to the CSS.
When the right property isn’t available or convenient, you can use
Element’s attributes property. This property is a Map<String, String>, where
the keys are attribute names. For a list of attribute names and their meanings,
see the MDN Attributes page. Here’s an example of setting an attribute’s
value:
elem.attributes['someAttribute'] = 'someValue';
Creating elements
You can add to existing HTML pages by creating new elements and attaching
them to the DOM. Here’s an example of creating a paragraph (<p>) element:
You can also create an element by parsing HTML text. Any child elements are
also parsed and created.
Attach the newly created element to the document by assigning a parent to the
element. You can add an element to any existing element’s children. In the
139
following example, body is an element, and its child elements are accessible
(as a List<Element>) from the children property.
document.body.children.add(elem2);
To add a node as the last child of its parent, use the List add() method:
querySelector('#inputs').nodes.add(elem);
querySelector('#status').replaceWith(elem);
Each element has a classes field, which is a list. Add and remove CSS classes
simply by adding and removing strings from this collection. For example, the
following sample adds the warning class to an element:
It’s often very efficient to find an element by ID. You can dynamically set an
element ID with the id property:
140
You can reduce the redundant text in this example by using method cascades:
While using IDs and classes to associate an element with a set of styles is
best practice, sometimes you want to attach a specific style directly to the
element:
message.style
..fontWeight = 'bold'
..fontSize = '3em';
Handling events
To respond to external events such as clicks, changes of focus, and
selections, add an event listener. You can add an event listener to any
element on the page. Event dispatch and propagation is a complicated
subject; research the details if you’re new to web programming.
Events can propagate up and down through the DOM tree. To discover which
element originally fired the event, use e.target:
document.body.onClick.listen((e) {
final clickedElem = e.target;
// ...
});
To see all the events for which you can register an event listener, look for
“onEventType” properties in the API docs for Element and its subclasses.
Some common events include:
change
blur
keyDown
141
keyUp
mouseDown
mouseUp
try {
var data = await HttpRequest.getString(jsonUri);
// Process data...
} catch (e) {
// Handle exception...
}
If you need access to the HttpRequest, not just the text data it retrieves, you
can use the request() static method instead ofgetString(). Here’s an example
of reading XML data:
142
// Successful URL access...
}
// ···
}
You can also use the full API to handle more interesting cases. For example,
you can set arbitrary headers.
The general flow for using the full API of HttpRequest is as follows:
For example:
143
'Content-type',
'application/x-www-form-urlencoded',
)
..send(encodeMap(data));
await request.onLoadEnd.first;
if (request.status == 200) {
// Successful URL access...
}
// ···
}
var ws = WebSocket('ws://echo.websocket.org');
Sending data
To send string data on the WebSocket, use the send() method:
Receiving data
To receive data on the WebSocket, register a listener for message events:
ws.onMessage.listen((MessageEvent e) {
print('Received message: ${e.data}');
});
print("Connecting to websocket");
void scheduleReconnect() {
if (!reconnectScheduled) {
Timer(Duration(seconds: retrySeconds),
() => initWebSocket(retrySeconds * 2));
}
reconnectScheduled = true;
}
ws.onOpen.listen((e) {
print('Connected');
ws.send('Hello from Dart!');
});
ws.onClose.listen((e) {
print('Websocket closed, retrying in ' +
'$retrySeconds seconds');
scheduleReconnect();
});
ws.onError.listen((e) {
print("Error connecting to ws");
scheduleReconnect();
});
ws.onMessage.listen((MessageEvent e) {
print('Received message: ${e.data}');
});
}
Plus d'information
This section barely scratched the surface of using the dart:html library. For
more information, see the documentation for dart:html. Dart has additional
libraries for more specialized web APIs, such as web
audio, IndexedDB, and WebGL.
For more information about Dart web libraries, see the web library overview.
145
dart:io - I/O for servers and
command-line apps
The dart:io library provides APIs to deal with files, directories, processes,
sockets, WebSockets, and HTTP clients and servers.
Important: Only Flutter mobile apps, command-line scripts, and servers can
import and use dart:io, not web apps.
The few synchronous methods in the dart:io library are clearly marked with a
Sync suffix on the method name. Synchronous methods aren’t covered here.
import 'dart:io';
146
print('The file is ${contents.length} characters
long.');
Handling errors
To capture errors so they don’t result in uncaught exceptions, you can register
a catchError handler on the Future, or (in an async function) use try-catch:
import 'dart:io';
import 'dart:convert';
147
var lines =
utf8.decoder.bind(inputStream).transform(LineSplitter());
try {
await for (var line in lines) {
print('Got ${line.length} characters from stream');
}
print('file is now closed');
} catch (e) {
print(e);
}
}
To add to the end of the file, use the optional mode parameter to
specify FileMode.append:
try {
var dirList = dir.list();
await for (FileSystemEntity f in dirList) {
if (f is File) {
print('Found file ${f.path}');
148
} else if (f is Directory) {
print('Found dir ${f.path}');
}
}
} catch (e) {
print(e.toString());
}
}
Refer to the API docs for File and Directory for a full list of methods.
HTTP server
The HttpServer class provides the low-level functionality for building web
servers. You can match request handlers, set headers, stream data, and
more.
The following sample web server returns simple text information. This server
listens on port 8888 and address 127.0.0.1 (localhost), responding to requests
for the path /dart. For any other path, the response is status code 404 (page
not found).
149
void processRequest(HttpRequest request) {
print('Got request for ${request.uri.path}');
final response = request.response;
if (request.uri.path == '/dart') {
response
..headers.contentType = ContentType(
'text',
'plain',
)
..write('Hello from the server');
} else {
response.statusCode = HttpStatus.notFound;
}
response.close();
}
HTTP client
The HttpClient class helps you connect to HTTP resources from your Dart
command-line or server-side application. You can set headers, use HTTP
methods, and read and write data. The HttpClient class does not work in
browser-based apps. When programming in the browser, use the dart:html
HttpRequest class. Here’s an example of using HttpClient:
Plus d'information
This page showed how to use the major features of the dart:io library. Besides
the APIs discussed in this section, the dart:io library also provides APIs
for processes, sockets, and web sockets. For more information about server-
side and command-line app development, see the server-side Dart overview.
150
Summary
This page introduced you to the most commonly used functionality in Dart’s
built-in libraries. It didn’t cover all the built-in libraries, however. Others that
you might want to look into include dart:collection and dart:typed_data, as well
as platform-specific libaries like theDart web development libraries and
the Flutter libraries.
You can get yet more libraries by using the pub package manager.
The collection, crypto, http, intl, and test libraries are just a sampling of what
you can install using pub.
To learn more about the Dart language, see the Visite du langage.
151