100% ont trouvé ce document utile (1 vote)
1K vues45 pages

Chapitre 2 Les Bases de Dart Pour Flutter MR NDIAYE

Transféré par

Ousin Faye
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
100% ont trouvé ce document utile (1 vote)
1K vues45 pages

Chapitre 2 Les Bases de Dart Pour Flutter MR NDIAYE

Transféré par

Ousin Faye
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Chapitre 2 : Les bases de Dart pour

Flutter
Environnement Dart
Dans ce chapitre nous allons apprendre les bases du langage Dart qui vont nous
permettre de coder nos premières applications Flutter.

Exécuter du Dart
Vous avez plusieurs moyens d'exécuter du Dart et nous allons vous les apprendre.

1. Exécuter du Dart localement


Il faut d’abord récupérer le chemin vers sdk de dart dans :
D:\tools\src\flutter\bin\cache\dart-sdk\bin.
Dans la barre de recherche Windows tapez "environnement" ou "env" puis
sélectionnez Modifier Variables d'environnement puis Variables d'environnement,
cherchez la variable Path puis ajouter le chemin vers le sdk de dart
Ou bien Cliquez sur "Parcourir…" et allez dans le dossier où vous avez extrait Flutter

2. Utiliser le Dart Pad


Une autre manière est d'utiliser le Dart Pad mis à disposition par Google.
Vous pouvez le retrouver ici.

DartPad
An online Dart editor with support for console, web, and Flutter apps.
https://dartpad.dev/

Bases de Dart

Chapitre 2 : Les bases de Dart pour Flutter 1


En Dart tout est un objet, tout ce que vous placez dans une variable est un objet. Un
objet est une instance de la classe Object, ce qui signifie que tout en Dart hérite de la
classe Object.
Dart est un langage typé comme par exemple Java ou Typescript. Mais comme pour
Typescript, les types peuvent être inférés (c'est-à-dire détectés automatiquement) dans
certains cas.

NB: Dart peut être transpilé en JavaScript

Si vous connaissez Java, JavaScript ou Typescript, apprendre les bases de Dart sera
extrêmement simple et ne nécessitera que ce chapitre !
Nous allons commencer par un petit Hello World ! comme l'usage nous y oblige ;)
En Dart chaque application doit avoir une fonction main() qui sert d'entrée dans
l'application.
Voici l'exemple :

Les variables en Dart


Les variables
Les variables stockent des références à des objets, et comme nous l'avons vu tout est
un objet en Dart. Donc une chaîne de caractères est un objet par exemple.
Ce qui est différent du JavaScript qui stocke les valeurs pour les types primitifs et des
références pour les objets.

Chapitre 2 : Les bases de Dart pour Flutter 2


var permet de déclarer une variable sans déclarer son type.
Par exemple :

var prenom = 'Babacar';

Ici, nous avons une variable qui stocke une référence à un objet String.
Nous n'avons pas besoin de spécifier le type car il est inféré par Dart automatiquement.

En revanche, les variables ne sont pas typées dynamiquement en Dart, contrairement


au JavaScript.

Cela signifie que si vous écrivez :

var prenom = 'Babacar';


prenom = 27;

Vous aurez une erreur car prenom a été typé en String automatiquement par Dart, et
son type ne peut pas être modifié ultérieurement.

Définir une variable typée


Nous pourrions cependant typer la variable directement.

Pour cela il faut déclarer un des types Dart : numbers, strings, booleans, lists, sets,
maps, runes et les symbols.

1. Numbers (Nombres)
Les nombres en Dart représentent les valeurs numériques. Il existe deux types de
nombres : les entiers (int) et les décimaux qui sont des nombres flottants(double).
Les nombres peuvent être utilisés pour effectuer des calculs mathématiques et des
opérations arithmétiques.
Exemple :

int age = 25;


double prix= 19.99;

Le type num

En Dart num est un type générique qui représente tous les types numériques, à la
fois les entiers et les décimaux. Il peut être utilisé pour stocker des valeurs
numériques sans se soucier du type spécifique.
Voici un exemple d'utilisation du type num :

Chapitre 2 : Les bases de Dart pour Flutter 3


num prix= 19.99; // Le type de la variable prix est déterminé a
num quantite = 5;
num total = prix* quantite ;

print(total); // Affiche : 99.95

Dans cet exemple, la variable prix est déclarée avec le type num et est initialisée
avec une valeur décimale. La variable quantite est également de type num et
stocke un entier. En multipliant prix par quantite , nous obtenons le total, qui est
également de type num .
Le type num est utile lorsque vous voulez travailler avec des valeurs numériques
sans vous soucier du type spécifique (int ou double). Cependant, il convient de
noter que si vous utilisez le type num , certaines opérations spécifiques aux
entiers ou aux décimaux peuvent ne pas être disponibles, car elles dépendent
du type sous-jacent.
Si vous avez besoin d'opérations spécifiques aux entiers ou aux décimaux, il est
recommandé d'utiliser les types int ou double respectivement, plutôt que le
type générique num .

2. Strings (Chaînes de caractères)


Les chaînes de caractères en Dart sont utilisées pour représenter du texte. Elles sont
entourées de guillemets simples (' ') ou doubles (" "). Les chaînes peuvent contenir
des lettres, des chiffres, des symboles et des espaces.

Exemple :

String message = "Bonjour, comment ça va ?";

3. Booleans (Booléens)
Les booléens en Dart représentent les valeurs logiques. Ils peuvent être soit vrai
(true) soit faux (false). Les booléens sont couramment utilisés pour les décisions
conditionnelles et les expressions logiques.

Exemple :

bool isActive = true;


bool isLogged = false;

4. Lists (Listes)

Chapitre 2 : Les bases de Dart pour Flutter 4


Les listes en Dart sont des collections ordonnées d'éléments. Elles peuvent contenir
différents types de données et être de taille variable. Les éléments d'une liste sont
accessibles par leur indice, qui commence à 0.
Exemple :

List<int> numbers = [1, 2, 3, 4, 5];


List<String> names = ['Alice', 'Bob', 'Charlie'];

5. Sets (Ensembles)
Les ensembles en Dart sont des collections non ordonnées d'éléments uniques. Ils
ne permettent pas d'avoir des doublons. Les ensembles sont utiles lorsque vous
avez besoin de vérifier rapidement si un élément est présent ou non.

Exemple :

Set<int> uniqueNumbers = {1, 2, 3, 4, 5};

6. Maps (Dictionnaires)
Les dictionnaires en Dart, également appelés maps, sont des collections
d'associations clé-valeur. Chaque élément est composé d'une clé unique et d'une
valeur correspondante. Les clés doivent être uniques, mais les valeurs peuvent être
dupliquées.
Exemple :

Map<String, String> capitals = {


'Senegal': 'Dakar',
'United States': 'Washington D.C.',
'Japan': 'Tokyo'
};

7. Runes
Les runes en Dart représentent un point de code Unicode. Ils sont utilisés pour
manipuler des caractères Unicode spécifiques, tels que des emojis ou des
caractères internationaux.
Exemple :

Rune heart = '\u2764'.runes.first;


print(String.fromCharCode(heart)); // Affiche : ❤

Chapitre 2 : Les bases de Dart pour Flutter 5


String heart = '\u2764';

print(heart);

8. Symbols (Symboles)

Les symboles en Dart sont utilisés pour représenter des identifiants uniques. Ils sont
souvent utilisés dans les métaprogrammes ou les réflexions pour identifier des
éléments tels que des fonctions, des classes ou des variables.
Exemple :

Symbol methodName = Symbol('myMethod');

Ces types de données en Dart sont utilisés pour représenter et manipuler différentes
valeurs dans vos programmes. En comprenant ces types, vous pouvez créer des
variables et des structures de données appropriées pour votre application.

Interpolation de variable
Comme en JavaScript, vous pouvez interpoler des variables avec $var ou ${var} :

Concaténation de chaînes de caractères et les chaînes multilignes


La concaténation et l'écriture sur plusieurs lignes de chaînes de caractères est
extrêmement pratiques en Dart :

Chapitre 2 : Les bases de Dart pour Flutter 6


Les constantes
En Dart il existe deux types de constantes : const et final.

Les const sont des constantes qui doivent être définies au moment de la compilation.
Elles sont initialisées et assignées au même moment.

Les final sont des constantes, qui ne peuvent donc être initialisées qu'une seule fois,
mais qui peuvent être assignées pendant l'exécution. Autrement dit, elles peuvent
recevoir une valeur déterminée au moment de l'exécution.

void main() {
// Deux moyens de déclarer des const :
const pi = 3.14;
const double pi2 = 3.13;

// Ne compilera pas :
pi = 24;

// Même chose pour les finals :


final x = 1;
final int y = 2;

// La différence entre les deux :


const t = DateTime.now(); // ne compilera pas !
final t = DateTime.now(); // valeur connue lors de l'exécution mai
}

Il y a quelques erreurs dans le code fourni :

1. Les constantes (const) ne peuvent pas être réassignées une fois qu'elles ont été
déclarées. Par conséquent, la ligne pi = 24; entraînera une erreur de compilation.

Chapitre 2 : Les bases de Dart pour Flutter 7


Pour corriger cela, vous devez soit utiliser final au lieu de const , soit choisir une
nouvelle valeur lors de la déclaration initiale.

2. Dans la ligne const t = DateTime.now(); , vous essayez de déclarer une constante en


utilisant DateTime.now() , qui est une valeur dynamique et ne peut pas être évaluée au
moment de la compilation. Par conséquent, cela entraînera également une erreur de
compilation. Si vous avez besoin d'une valeur constante basée sur l'heure actuelle,
vous devrez la déclarer comme final plutôt que const .

Les lists et les map


1. Les lists
Les listes sont comme des tableaux en JavaScript.

Définir une list


Pour définir une liste vous pouvez utiliser var et des crochets [ ] :

var maListe = [1, 2, 3];

Ici, Dart va inférer que le type est List<int>, c'est-à-dire qu'il va attribuer
automatiquement le type List contenant des int.
Il ne sera donc pas possible d'ajouter autre chose :

var maListe = [1,2,3];

maListe.add('Hello !'); // Error: The argument type 'String'


// can't be assigned to the parameter type 'int'.

Vous pouvez également définir explicitement une list et la typer comme vous le
souhaitez :

List<int> maListe = [1,2,3];

La propriété length
Comme en JavaScript, les lists commencent à l'index 0.
Les lists ont une propriété length pour connaître la longueur de celle-ci.
Le dernier élément d'une list est donc à l'index list.length - 1.

Chapitre 2 : Les bases de Dart pour Flutter 8


Accéder à un élément d'une list
Pour accéder à un élément d'une list, il suffit de faire list[index].

var list = [1, 2, 3];


list[1]; // 2

L'opérateur spread (...)


Comme en JavaScript depuis ES6, Dart permet d'utiliser l'opérateur spread pour
copier facilement une list dans une autre list :

Quelques méthodes
Il existe environ 50 méthodes en Dart pour les lists. Nous les verrons au fur à
mesure dès que nous en aurons besoin.
Mais nous allons voir quelques méthodes basiques dès maintenant pour les lists :
add(), addAll(), clear(), indexOf(), contains(), remove() et removeAt().

void main() {
var list = [1,2,1];

// Ajouter une valeur à la fin de la List :


list.add(2);

// Enlever la première occurence d'une valeur spécifique d'une


// Retourne true si un élément a été enlevé, false sinon.
list.remove(1);
print(list);

// Enlever l'élément à l'index spécifié :


list.removeAt(0);
print(list);

// Enlever tous les éléments de la List :


list.clear();

Chapitre 2 : Les bases de Dart pour Flutter 9


print(list);

// Ajouter tous les éléments passés dans une list à la fin de la


list.addAll([1,2,3]);
print(list);

// Retourne l'index de l'élément :


print(list.indexOf(1));

// Retourne un booléen suivant que l'élément est dans la List o


print(list.contains(22));
}

2. Les maps
Un map est un objet qui associe des clés et des valeurs. Les clés et les valeurs
peuvent avoir tout type d'objet.
Les clés doivent être uniques mais pas les valeurs.
En fait, les maps en Dart sont extrêmement semblables aux maps en JavaScript. Il
n'existe par contre pas d'objets littéraux comme en JavaScript.

Définir un map
Vous pouvez définir un map avec var :

var map = {
'clé1': 'valeur1',

Chapitre 2 : Les bases de Dart pour Flutter 10


'clé2': 'valeur2'
};

Vous pouvez également typer un map :

Map<String, String> map1 = {'clé1': 'valeur1'};


Map<int, String> map2 = {1: 'valeur1'};
Map<String, double> map3 = {'clé3': 45.22};

Accéder à un élément d'un map


Vous pouvez simplement utiliser map[cle] :

Map<String, String> map1 = {'clé1': 'valeur1'};


Map<int, String> map2 = {1: 'valeur1'};
Map<String, double> map3 = {'clé3': 45.22};

print(map1['clé1']); // 'valeur1'
print(map2[1]); // 'valeur1'
print(map3['clé3']); // 45.22

La propriété length
Les maps ont également une propriété length qui fonctionne de la même manière
que pour les lists.

Quelques autres propriétés


Nous allons voir les propriétés values, keys et entries :

var map1 = {
'clé1': 'valeur1',
1: 'valeur2'
};

// La propriété entries permet d'obternir les paires clé/valeur


print(map1.entries);

// La propriété values permet d'obtenir les valeurs :


print(map1.values);

Chapitre 2 : Les bases de Dart pour Flutter 11


// La propriété keys permet d'obtenir les clés :
print(map1.keys.runtimeType);

Opérateur spread
Il est possible d'utiliser l'opérateur spread avec un map également :

void main() {
var map1 = {
'clé1': 'valeur1',
1: 'valeur2'
};

var map2 = {
...map1,
'clé3': 44.23
};

print(map2);//{clé1: valeur1, 1: valeur2, clé3: 44.23}


}

Quelques méthodes
Nous allons voir quelques méthodes basiques pour les maps : containsKey,
containsValue et remove :

Chapitre 2 : Les bases de Dart pour Flutter 12


void main() {
var map1 = {
'clé1': 'valeur1',
1: 'valeur2'
};

// containsKey() permet de savoir si une clé existe :


print(map1.containsKey('clé1'));//true

// containsValue() permet de savoir si une valeur existe :


print(map1.containsValue(1));//false

// remove() permet de supprimer une paire clé/valeur :


map1.remove('clé1');
print(map1);//{1: valeur2}
}

Bien sûr nous sommes loin d'avoir fait le tour des lists et des maps en Dart ! Mais
c'est une approche suffisante pour commencer Flutter.

Les fonctions
Les fonctions en Dart
Comme le reste en Dart, les fonctions sont des objets.

Elles peuvent donc être assignées à des variables et passées comme arguments à
d'autres fonctions.

En Dart il est recommandé de typer le retour des fonctions, par exemple :

void direBonjour() {
print('Bonjour');
}
direBonjour();

Ici la fonction ne retourne rien car print() retourne void.


Une fonction doit toujours return quelque chose, si nous n'utilisons pas return, alors
return null; est ajouté par défaut à la fonction.

Chapitre 2 : Les bases de Dart pour Flutter 13


Vous pouvez omettre le type retourné et cela fonctionnera, mais ce n'est pas
recommandé.

Les fonctions fléchées


En Dart il existe aussi des fonctions fléchées qui fonctionnent exactement comme en
JavaScript:
=> expression équivaut à { return expr; }.

Par exemple :

void direBonjour() => print('Bonjour');


direBonjour();

Les paramètres
En Dart il vaut mieux également typer les paramètres.

1. Typer les paramètres


Nous allons prendre un premier exemple :

void main() {
var nomComplet = getFullName('Babacar', 'NDIAYE');
print(nomComplet);
}

String getFullName(String prenom, String nom) {


return "$prenom $nom";
}

//Console
Babacar NDIAYE

Ce programme déclare une fonction getFullName qui prend deux paramètres : prenom

et nom de type String. Elle retourne une chaîne de caractères contenant la


combinaison du prénom et du nom séparés par un espace.

2. Paramètres nommés et null safety

Jusqu'à maintenant nous avons vu comment utiliser des paramètres positionnels.


En Dart, il est également possible d'utiliser des paramètres nommés pour cela il
suffit de faire lors de la définition :

Chapitre 2 : Les bases de Dart pour Flutter 14


nomFonction({param1, param2}) {}

Et lors de l'utilisation :

nomFonction(param1: val1, param2: val2);

Les paramètres nommés offrent plus de flexibilité lors de l'appel de fonctions en


spécifiant explicitement les noms des paramètres avec leurs valeurs
correspondantes.

NB: Les paramètres nommés sont optionnels sauf si vous utilisez


required devant le nom du paramètre.

Voici un exemple :

void main() {
var nomComplet = getFullName(nom: 'NDIAYE');
print(nomComplet);
}

String getFullName({required String prenom, required String nom})


return "$prenom $nom";
}
//Console
Error: Required named parameter 'prenom' must be provided.

Lors de le compilation de ce programme on aura une erreur puisque le paramètre


prénom est obligatoire.

Si vous utilisez des paramètres nommés et que vous ne fournissez pas une valeur
par défaut avec = (nous le verrons plus bas dans la leçon) ou que vous ne spécifiez
pas qu'ils sont obligatoires avec required, vous aurez une erreur.
En effet, dans ce cas, leur valeur par défaut est null et donc il faut le préciser en
ajoutant un ? à la fin du type.
Le point d'interrogation à la fin d'un type permet d'ajouter la valeur null à ce type.

En effet, Dart a une fonctionnalité appelée null safety (sécurité contre les null) qui
vous oblige à spécifier si une variable ou un paramètre peut contenir la valeur null
ou non.

Chapitre 2 : Les bases de Dart pour Flutter 15


Par défaut, Dart va considérer qu'il n'est pas possible que la valeur soit null. Il faut
donc utiliser le point d'interrogation pour le permettre.

Voici un exemple :

void main() {
var nomComplet = getFullName(prenom: 'Babacar', nom: 'NDIAYE');
print(nomComplet);
}

String getFullName({String? prenom, String? nom}) {


return "$prenom $nom";
}

3. Paramètres optionnels ou requis


En Dart, les paramètres peuvent être optionnels ou obligatoires.

Par défaut les paramètres positionnels sont obligatoires :

void main() {
var nomComplet = getFullName('Babacar'); // Error: Too few posi
// 2 required, 1 given.

print(nomComplet);
}

String getFullName(String prenom, String nom) {


return "$prenom $nom";
}

Pour rendre un paramètre optionnel il faut utiliser [param] :

void main() {
var nomComplet = getFullName('Babacar');
print(nomComplet);
}

String getFullName(String prenom, [String? nom]) {


return "$prenom $nom";
}

Chapitre 2 : Les bases de Dart pour Flutter 16


//Console
Babacar null

4. Paramètres par défaut


Il est également possible de définir la valeur par défaut des paramètres en Dart.

Pour cela il suffit de faire : type param = valeurParDefaut.


Comme précisé plus haut, lorsqu'un paramètre est optionnel, il faut soit lui donner
une valeur par défaut, soit préciser que la valeur peut être null en ajoutant un ? à la
fin du type :

void main() {
var nomComplet = getFullName();
print(nomComplet);
}

// Fonction avec deux paramètres optionnels et dont


// le premier paramère a une valeur par défaut :
String getFullName([String prenom = 'Inconnu', String? nom]) {
return "$prenom $nom";
}
//Console
Inconnu null

Même chose avec les paramètres nommés :

void main() {
var nomComplet = getFullName(prenom: 'Babacar');
print(nomComplet);
}

// Fonction avec deux paramètres optionnels et dont


// le premier paramère a une valeur par défaut :
String getFullName({String? prenom, String nom = 'Inconnu'}) {
return "$prenom $nom";
}

Chapitre 2 : Les bases de Dart pour Flutter 17


//Console
Babacar Inconnu

Les fonctions anonymes


Comme en JavaScript, il est possible d'utiliser des fonctions anonymes appelées
également lambdas ou fonctions fléchées:

([[Type] param1[, …]]) {


codeBlock;
};

Par exemple :

void main() {
List<int> list = [1,2,3,4];

list.forEach((item) {
print(item);
});
print('\nFonction fléchée anonyme\n');
// Ou encore avec une fonction fléchée anonyme :
list.forEach((item) => print(item));
}
//Console
1
2
3
4

Fonction fléchée anonyme

1
2
3
4

Attention ! Contrairement au JavaScript, si vous n'avez qu'un seul paramètre dans une
fonction fléchée anonyme vous ne pouvez pas omettre les parenthèses.

Chapitre 2 : Les bases de Dart pour Flutter 18


Voici un exemple pour clarifier cela :

void main() {
var numbers = [1, 2, 3, 4, 5];

// Utilisation d'une fonction fléchée anonyme avec un seul paramèt


var squares = numbers.map((number) => number * number);

print(squares.toList()); // Affiche : [1, 4, 9, 16, 25]


}

Dans cet exemple, nous utilisons une fonction fléchée anonyme avec un seul paramètre
number pour calculer le carré de chaque nombre dans la liste numbers . La syntaxe (number)

=> number * number est utilisée pour définir la fonction fléchée anonyme.

Notez que les parenthèses autour du paramètre number sont nécessaires. Si vous
essayez de les omettre en utilisant simplement number => number * number , cela entraînera
une erreur de syntaxe.
Donc, pour récapituler, lorsque vous utilisez une fonction fléchée anonyme en Dart avec
un seul paramètre, assurez-vous d'inclure les parenthèses autour du paramètre. Cela
garantit que votre code est correctement interprété par le compilateur Dart.

Passer des fonctions comme argument à d'autres fonctions


Comme en JavaScript, les fonctions peuvent être passées en argument à d'autre
fonction.
Nous pouvons donc écrire :

main() {
List<int> list = [1,2,3,4];

list.forEach(print);
}

Voici un autre exemple avec une fonction fléchée que nous définissons :

void main() {
List<String> list = ['je', 'suis', 'en', 'lowercase'];

var listUpper = list.map(toUpperCase);

Chapitre 2 : Les bases de Dart pour Flutter 19


print(listUpper);
}

String toUpperCase(String elem) => elem.toUpperCase();

//Console
(JE, SUIS, EN, LOWERCASE)

void main() {
var result = calculate(5, 3, (a, b) => a + b);
print(result);
}

int calculate(int a, int b, int Function(int, int) operation) {


return operation(a, b);
}

//Console
8

Dans cet exemple, nous avons une fonction anonyme passée comme argument à la
fonction calculate . La fonction anonyme prend deux paramètres a et b , et retourne la
somme des deux nombres.
La fonction calculate elle-même prend trois paramètres : a , b et operation . operation est
une fonction qui attend deux entiers et retourne un entier. Dans notre cas, nous passons
une fonction anonyme (a, b) => a + b comme operation , qui effectue simplement
l'addition des deux nombres.
Lorsque nous appelons calculate(5, 3, (a, b) => a + b) , la fonction calculate exécute
l'opération fournie (dans notre cas, l'addition) en utilisant les valeurs 5 et 3 comme
arguments, et retourne le résultat 8 . Ce résultat est ensuite stocké dans la variable
result et affiché à l'aide de la fonction print .

Les fonctions anonymes en Dart sont utiles lorsque vous souhaitez définir des
fonctionnalités spécifiques à un certain contexte ou lorsque vous souhaitez passer des
fonctions en tant qu'arguments à d'autres fonctions. Elles offrent une flexibilité et une
expressivité accrues dans la manière dont vous définissez et utilisez les fonctions dans
votre code.
Les structures de contrôle

Chapitre 2 : Les bases de Dart pour Flutter 20


Les blocs conditionnels
Comme dans la plupart des langages nous pouvons utiliser if, else et else if :

void main() {
bool test1 = false;
bool test2 = true;

if (test1) {
print('Par là !');
} else if (test2) {
print('Ici !');
} else {
print('Là !');
}
}

A noter qu'il n'y a pas de coercition contrairement au JavaScript. Cela signifie qu'une
chaîne de caractères ne sera pas transformée en true par exemple, dans un contexte de
test.
Vous ne pouvez donc pas écrire :

void main() {
String test1 = 'J\'existe !';
bool test2 = true;

if (test1) { // Error: A value of type 'String' can't be assigned


// a variable of type 'bool'.
print('Par là !');
} else if (test2) {
print('Ici !');
} else {
print('Là !');
}
}

Vous devez écrire :

void main() {
String test1 = 'J'existe !';

Chapitre 2 : Les bases de Dart pour Flutter 21


bool test2 = true;

if (test1 != null) {
print('Par là !'); // Par là !
} else if (test2) {
print('Ici !');
} else {
print('Là !');
}
}

L'opérateur ternaire
Comme en JavaScript vous pouvez utiliser des ternaires.

void main() {
int age = 17;

bool isMajeur = age >= 18 ? true : false;


print(isMajeur);//false
}

Les boucles
En Dart, nous pouvons utiliser les boucles for, while et do/while.

Les boucles for

Les boucles for fonctionnent pareil qu'en JavaScript :

void main() {
for (int i = 0; i < 5; i++) {
print('Hello ${i + 1}');
}
}

Vous pouvez utiliser également forEach sur des itérables commes les List, mais
vous ne pouvez pas accéder à l'index de l'itération en cours :

void main() {
List<int> liste = [1, 2, 3];

Chapitre 2 : Les bases de Dart pour Flutter 22


int result = 0;

liste.forEach((elem) => result = result + elem);


print(result);
}

Vous pouvez également utiliser for … in :

void main() {
List<int> liste = [1, 2, 3];
int result = 0;

for (var e in liste) {


result = result + e;
}

print(result);
}

Les boucles while

Les boucles while() permettent d'exécuter un bloc d'instructions tant qu'une


condition n'est pas remplie :

void main() {
List<int> liste = [1, 2, 3];

while (liste.isNotEmpty) {//liste.length != 0


print(liste);
liste.removeLast();
}

print(liste);
}
//Console
[1, 2, 3]
[1, 2]
[1]
[]

Chapitre 2 : Les bases de Dart pour Flutter 23


Les boucles do / while

Avec les boucles do / while, la condition est évaluée après la boucle :

void main() {
List<int> liste = [1, 2, 3];

do {
print(liste);
liste.removeLast();
} while (liste.length != 0);

print(liste);
}
//Console
[1, 2, 3]
[1, 2]
[1]
[]

Utilisation de break et continue


break permet d'arrêter la boucle si une condition survient..

continue permet de sauter une itération suivant une condition.

void main() {
List<int> liste = [1, 2, 3];

print("break");
while (liste.length != 0) {
// Si la liste n'a plus qu'un élément nous stoppons la boucle
if (liste.length == 1) break;
print(liste);
liste.removeLast();
}
print("continue");
for (var i = 2; i < 10; i++) {
// Nous sautons l'itération si i est pair :
if (i % 2 == 0) continue;
// Donc seuls les éléments impairs sont ajoutés :

Chapitre 2 : Les bases de Dart pour Flutter 24


liste.add(i);
}

print(liste);
}
//Console
break
[1, 2, 3]
[1, 2]
continue
[1, 3, 5, 7, 9]

Les switch / case


Un switch / case permet de comparer une valeur à un int ou à un string.

void main() {
const int a = 3;
switch (a) {
case 1:
print('Ici');
break;
case 2:
print('là');
break;
default:
print('LA !');
break;
}
}

//Console
LA !

Les classes
Généralités sur les classes en Dart
En Dart tous les objets sont les instances d'une classe, et toutes les classes
descendent de la classe Object.

Chapitre 2 : Les bases de Dart pour Flutter 25


En Dart , toutes les classes ont exactement une classe parente, appelée superclass,
sauf la classe Object.

Créer une classe


Pour créer une classe il suffit de faire :

class Point {
}

Pour obtenir une instance d'une classe il suffit de faire :

var instance1 = new Point();


// ou car new est optionnel en Dart :
var instance2 = Point();

Le contenu des classes


Les classes peuvent contenir des fonctions, appelées méthodes, et des données,
appelées variables d'instance.
Nous allons commencer par voir les variables d'instance, puis nous verrons les
méthodes après avoir étudié les constructeurs.

Les variables d'instance


Pour définir des variables d'instance il suffit de faire :

class Point {
// Déclaration d'une variable d'instance x de type num et initiali
num? x;
// Déclaration d'une variable d'instance y de type num et initiali
num y = 0;
}

Notez le point d'interrogation après le type num. Il signifie que la


variable peut être nulle.

Depuis une version récente de Dart, a été introduit la "null safety", à savoir qu'il faut
explicitement déclarer qu'une variable ou un argument peut être nul en ajoutant un point
d'interrogation. C'est une vérification supplémentaire introduite par Dart.

Chapitre 2 : Les bases de Dart pour Flutter 26


Pour invoquer une méthode ou utiliser une propriété sur l'instance d'une classe il faut
utiliser .methode() ou .propriete.

Les constructeurs
En Dart les constructeurs de base ont le même nom que la classe auxquels ils
appartiennent et ce sont de simples fonctions :

class Point {
// raccourci syntaxique pour déclarer deux variables du même type
num? x, y;

Point(num x, num y) {
this.x = x;
this.y = y;
}
}

Ici, this se réfère à l'instance courante. En Dart, nous n'utilisons this que dans le cas
d'un conflit de nom.
En effet, ici la classe et le constructeur ont le même temps, et c'est pour cette raison
que nous utilisons this pour se référer à l'instance courante.

Il existe un raccourci syntaxique pour écrire exactement le même constructeur :

class Point {
num? x, y;

Point(this.x, this.y);
}

Les constructeurs nommés


Les constructeurs nommés, ou named constructor permettent d'avoir plusieurs
constructeurs dans une même classe !
Pour créer d'autres constructeurs, il suffit d'utiliser NomClasse.NomConstructeur(),
comme ici :

class Point {
num? x, y;

Chapitre 2 : Les bases de Dart pour Flutter 27


Point(this.x, this.y);

Point.origin() {
x = 0;
y = 0;
}
}

Les méthodes d'instance


Les méthodes d'instance sont des fonctions définies sur une classe et accessibles
sur les instances de cette classe.
Voici un exemple de méthode d'instance :

import 'dart:math';

void main() {

// Nous créons deux instances de la classe Point :


Point point1 = Point(10, 2);
Point point2 = Point(22, 11);

// Puis nous invoquons la méthode distanceTo :


num distance = point1.distanceTo(point2);
print(distance);

class Point {
num x, y;

Point(this.x, this.y);

// Nous calculons la distance entre deux points


// sur un plan carthésien :
num distanceTo(Point autrePoint) {
num dx = x - autrePoint.x;
num dy = y - autrePoint.y;
return sqrt(dx * dx + dy * dy);

Chapitre 2 : Les bases de Dart pour Flutter 28


}
}

Console
15

Les méthodes et les propriétés statiques


Par opposition aux méthodes d'instance et aux propriété d'instance, nous pouvons
définir des propriétés et méthodes qui ne seront accessibles que depuis l'objet de la
classe.
Elles ne seront pas accessibles sur les instances de la classe.
Pour ce faire, il suffit d'utiliser static :

class Homme {
String? prenom, nom;
static const genre = 'masculin';

Homme(this.prenom, this.nom);
static direBonjour() => print('Bonjour !');
}

void main() {
Homme babs = Homme('Babacar', 'NDIAYE');
print(Homme.genre); // masculin
Homme.direBonjour(); // Bonjour !
print(babs.genre); // Error: The getter 'genre' isn't defined for
}

Un autre exemple

class Homme {
String? prenom, nom, matricule;
static const genre = 'masculin';
static int code = 1;

Homme(this.prenom, this.nom, {String? matricule}) {


this.matricule = matricule ?? generateMatricule();
}

Chapitre 2 : Les bases de Dart pour Flutter 29


static direBonjour() => print('Bonjour !');

String generateMatricule(){
String nomFirstLetter = nom!.substring(0,1);
String prenomFirstLetter = prenom!.substring(0,1);
String id = code.toString().padLeft(4, '0');
code++;
return nomFirstLetter + prenomFirstLetter + id;
}

@override
String toString() {
return 'nom= ${nom ?? ''}\n'
'prenom= ${prenom ?? ''}\n'
'matricule= ${matricule ?? ''}';
}

void main() {
Homme babs = Homme('Babacar', 'NDIAYE');
Homme moha = Homme('Mohamed', 'NDIAYE');
print('$babs\n');
print(moha);

Ici, si la variable code n'était pas déclarée en tant que statique (static), chaque instance
de la classe Homme aurait son propre compteur initialisé à 1. En la déclarant statique, la
variable code est partagée entre toutes les instances de la classe.

Les interfaces
Une interface définit la syntaxe à laquelle une classe doit adhérer.
Les interfaces définissent un ensemble de méthodes disponibles sur un objet.

1. Les interfaces implicites

Chapitre 2 : Les bases de Dart pour Flutter 30


En Dart, il n'y a pas de déclaration d'interface, en effet chaque classe définit
implicitement une interface.

Cette interface contient toutes les propriétés et les méthodes implémentées sur la
classe, nous pouvons le voir comme le "type" d'une classe.
Elle comprend également toutes les interfaces implémentées par la classe.

2. L'implémentation d'interface
Lorsqu'une classe implémente une autre classe, cela signifie qu'elle déclare toutes
les propriétés définies sur la première classe.

Par exemple :

// Prenons une classe :


class ClasseA {
String? prop1;

ClasseA(this.prop1);

String methode1(String param) => 'Un $param.';


}

// La classe A a donc comme interface implicite, une propriété d'


// de type String, et une méthode qui prend en paramètre une Stri

class ClasseB implements ClasseA {


String prop1 = 'une valeur';
String? prop2;

String methode1(String param) => 'Retourne autre chose';


}

La ClasseB implémente la ClasseA car elle respecte son API. Elle doit contenir
toutes les propriétés et méthodes de la ClasseA mais peut en implémenter d'autres,
comme par exemple prop2.
Il faut également respecter les types des propriétés, les types du retour et des
paramètres de la ClasseA.
Nous reverrons des cas concrets plus tard.

3. Les classes abstraites

Chapitre 2 : Les bases de Dart pour Flutter 31


Parfois nous voulons définir des interfaces sans les implémenter directement.
Dans ce cas, en Dart, il faut utiliser une classe abstraite. Il s'agit en fait d'une classe
dont l'interface implicite ne sera implémentée que dans une autre classe.

Les classes abstraites ne peuvent pas être instanciée.


Elles peuvent être implémentées par d'autres classes.

abstract class UneClasseAbstraite {


String proprieteAbstraite;

void methodeAbstraite();
}

class UneClasseImplementee implements UneClasseAbstraite {


String proprieteAbstraite = 'valeur';

void methodeAbstraite() => print(proprieteAbstraite);


}

Nous appelons méthodes abstraites les méthodes définies sur une classe abstraite
car elles ne sont pas implémentés : elles ne font rien.

Les getters et les setters


Les getters et les setters sont des méthodes spéciales qui permettent de définir
comment des propriétés d'instance sont lus et / ou écrites.
Par défaut les propriétés d'instance ont un getter et un setter implicites :

import 'dart:math';

void main() {

Point point1 = Point(10, 2);


Point point2 = Point(22, 11);
num distance = point1.distanceTo(point2);

// Nous avons accès aux propriétés x et y des


// points grâce aux getters implicites :
print(point1.x);
print(point2.y);

Chapitre 2 : Les bases de Dart pour Flutter 32


// Nous pouvons également modifier les points
// grâce aux setters implicites :
point1.x = 9;
print(point1.x);
}

class Point {
num x, y;

Point(this.x, this.y);

num distanceTo(Point autrePoint) {


num dx = x - autrePoint.x;
num dy = y - autrePoint.y;
return sqrt(dx * dx + dy * dy);
}
}

Console
10
11
9

Mais il est possible de définir ses propres getters et setters également :

class Person {
String prenom, nom;

Person(this.prenom, this.nom);

// Nous créons un getter pour accéder au nom complet :


String get fullName => '$prenom $nom';

// Nous créons un setter pour extraire le prénom


// et le nom d'un nom complet :
set fullName(String nomComplet) {
prenom = nomComplet.split(' ')[0];
nom = nomComplet.split(' ')[1];
}

Chapitre 2 : Les bases de Dart pour Flutter 33


}

void main() {
Person babs = Person('Babacar', 'NDIAYE');
print(babs.fullName);

babs.fullName = 'Mohamed DIAKHATE';


print(babs.prenom);
print(babs.nom);
}

Console
Babacar NDIAYE
Mohamed
DIAKHATE

L'héritage
Contrairement au JavaScript, nous ne sommes pas dans un langage prototypal. Les
classes ne sont pas du sucre syntaxique.
L'héritage est la possibilité de créer des classes à partir d'autres classes.
Nous appelons la classe à partir duquelle une autre classe est créée la classe parente
ou la super class.
La classe créée à partir de la classe parente s'appelle la classe fille ou la sub class.
Il existe deux types d'héritage : l'héritage simple et l'héritage multiple.
L'héritage multiple est le fait qu'une classe peut hériter de plusieurs classes, ce n'est
pas possible dans Dart qui ne supporte que l'héritage simple.
En revanche Dart supporte l'héritage multi-niveaux : une classe peut hériter d'une
classe, héritant elle-même d'une autre classe.

1. Utilisation d'extends
Une classe hérite d'une autre classe en utilisant extends.
La classe fille hérite de toutes les propriétés et les méthodes de la classe parente,
mais pas de son constructeur.

void main() {
Enfant enfant = new Enfant();

Chapitre 2 : Les bases de Dart pour Flutter 34


enfant.direBonjour();
}
class Parent {
void direBonjour() {
print("Bonjour !!");
}
}
class Enfant extends Parent {}

2. Utilisation de super
Le mot clé super permet de se référer à la classe parente :

class ClasseParente {
void direBonjour() => print('Bonjour !');
}

class ClasseEnfant extends ClasseParente {

direBonjourEtAuRevoir() {
super.direBonjour();
print('Au revoir !');
}

void main() {
ClasseEnfant enfant = ClasseEnfant();
enfant.direBonjourEtAuRevoir();
}

Il est possible d'utiliser le constructeur de la classe parente dans la classe fille en


utilisant
: super :

class Person {
String prenom, nom;

Person(this.prenom, this.nom);
}

Chapitre 2 : Les bases de Dart pour Flutter 35


class Homme extends Person {
final sexe = 'masculin';

// Nous appelons le constructeur de la classe parente avec


// ": super" :
Homme(String prenom, String nom) : super(prenom, nom);

void main() {
Homme babs= Homme('Babacar', 'NDIAYE');
print(babs.prenom);
print(babs.nom);
print(babs.sexe);
}

3. Utilisation de @override

Si dans une classe fille vous voulez remplacer une méthode d'instance, un getter ou
un setter, vous pouvez utiliser l'annotation @override pour indiquer que vous
souhaitez faire la surcharge (override) d'une méthode.Cela permet de remplacer la
définition de la classe parente par une nouvelle implémentation dans la classe
enfant.

class ClasseParente {
void direBonjour() => print('Bonjour du parent !');
}

class ClasseEnfant extends ClasseParente {


@override
void direBonjour() => print('Bonjour de l'enfant !');
}

void main() {
ClasseEnfant enfant = ClasseEnfant();
enfant.direBonjour(); // Bonjour de l'enfant !
}

Chapitre 2 : Les bases de Dart pour Flutter 36


Dans cet exemple, la méthode direBonjour() de la classe ClasseParente est surchargée
dans la classe ClasseEnfant . L'annotation @override est utilisée pour indiquer
explicitement que vous faites la surcharge de la méthode parente.

Lorsque vous appelez la méthode direBonjour() sur une instance de la classe


ClasseEnfant , elle exécute la nouvelle implémentation définie dans la classe enfant,

qui affiche "Bonjour de l'enfant !" plutôt que "Bonjour du parent !".
L'utilisation de l'annotation @override est une bonne pratique en Dart pour assurer
que vous faites réellement la surcharge d'une méthode existante. Cela aide
également à détecter les erreurs de saisie de noms de méthodes ou de signatures
incorrectes lors de la surcharge.

Les types énumérés


Les types émunérés, souvent appelés enum sont un type spécifique de classe Dart qui
permettent de représenter un nombre fixe de valeurs constantes.

enum Direction { gauche, droite, devant, derriere }

Voici comment utiliser notre énumération :

enum Direction { gauche, droite, devant, derriere }

void main() {
Direction direction = Direction.gauche;
print(direction); // Affiche "Direction.gauche"

direction = Direction.droite;
print(direction); // Affiche "Direction.droite"

direction = Direction.devant;
print(direction); // Affiche "Direction.devant"

direction = Direction.derriere;
print(direction); // Affiche "Direction.derriere"
}

Il est possible d'accéder à toutes les valeurs d'un enum avec la propriété values :

List<Direction> directions = Direction.values;

Chapitre 2 : Les bases de Dart pour Flutter 37


Vous pouvez vous servir d'un enum pour les switch / case par exemple, vous aurez une
erreur si vous oubliez un cas :

enum Direction { gauche, droite, devant, derriere }

void main() {
var direction = Direction.devant;

switch (direction) {
case Direction.gauche:
print('A gauche !');
break;
case Direction.droite:
print('A droite !');
break;
case Direction.devant:
print('Devant !');
break;
case Direction.derriere:
print('Derriere !');
break;
}
}
Console
Devant !

Les génériques
Les generics permettent de spécifier qu'une collection en Dart ne peut contenir que des
valeurs d'un certain type.
Ils fonctionnent sur toutes les collections Dart. Pour le moment, nous avons vu deux
types de collections : les lists et les maps.
La syntaxe est la suivante :
Collection <type> identifiant = assignation
Nous en avons déjà vus dans le chapitre précédemment, voici un exemple :

Chapitre 2 : Les bases de Dart pour Flutter 38


List<String> noms = List<String>();
noms.addAll(['Babacar', 'Aminata']);
noms.add(42); // Error: The argument type 'int' can't be assigned to
// the parameter type 'String'.

Les collections qui utilisent des génériques sont appelés des collections type-safe.
Il est également possible d'utiliser un type indéfini souvent indiqué par T pour type, par
convention.
Nous pouvons également typer des fonctions et des méthodes avec un type générique
en faisant :

function<T> () { … };

Avec cette notation nous passons en paramètre un type générique que nous utiliserons
dans la fonction ou la méthode.
Prenons un exemple :

main() {
List<int> values = [1, 2, 4, 5];
print(soustraire(15, values));

List<double> doubleValues = [1.1, 2.231, 3.123, 4.21];


print(soustraire(15.0, doubleValues));
}

// Nous limitons le type de T avec extends à un num :


T soustraire<T extends num>(T values, List<T> items){
T x = values;
for (var value in items) {
x = (x - value) as T;
}
return x;
}

Dans cette exemple nous définissons une fonction soustraire() et nous la typons en
indiquant qu'elle va retourner un type T, nous restreignons également les arguments
qu'elle peut recevoir grâce à extends.

Chapitre 2 : Les bases de Dart pour Flutter 39


En effet, <T extends num> signifie que T ne peut être qu'un num donc un double ou un
int.

Ensuite, nous typons également ses paramètres avec T et List<T>.


Ainsi, nous pouvons appeler la fonction soustraire avec des types numériques (tels que
int ou double ) et elle effectuera la soustraction correctement en respectant le type

spécifié.

Les génériques en Dart sont utiles lorsque vous souhaitez créer des structures de
données et des fonctions réutilisables, tout en assurant le type de sécurité et en évitant
les erreurs de type.

Les imports et les exports


Importer une librairie
Importer une librairie la rend accessible dans le fichier où elle est importée.
Les fichiers Dart peuvent avoir autant d'imports que nécessaire.

Utiliser import
Pour importer une librairie il suffit de faire, par exemple pour une librairie native :

import 'dart:math'

Une fois une librairie importée vous pouvez utiliser toutes ses fonctions :

import 'dart:math';
void main() {
print("La racine carrée de 16 est : ${sqrt(16)}");
}

Pour les librairies non natives il faut faire :

import 'package:test/test.dart';

Pour les fichiers, il suffit de passer le chemin vers le fichier à importer directement.

Les conflits de noms


Si deux librairies ont des conflits de noms vous pouvez utiliser as pour la renommer lors
de l'import.

Chapitre 2 : Les bases de Dart pour Flutter 40


Prenons un exemple où deux librairies ont une classe appelée Couleur, si vous
importiez les deux sans as, vous ne pourriez l'utiliser à cause du conflit de nom :

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// Utiliser la classe Couleur de la lib1 :


Couleur instance1 = Couleur();

// Utiliser la classe Couleur de la lib2 :


lib2.Couleur instance2 = lib2.Couleur();

Quand vous utilisez as il faut forcément préfixer vos appels avec le nom donné à la
librairie.

Les imports partiels


Pour importer que certaines parties d'une librairie il suffit d'utiliser hide et show.

// Importe SEULEMENT pi
import 'package:lib1/lib1.dart' show pi;

// Tout importer SAUF pi


import 'package:lib2/lib2.dart' hide pi;

Les imports lazy


En Dart, il est possible de lazy loader une librairie en utilisant deferred as.
C'est-à-dire que la librairie ne sera chargée que lorsqu'elle sera utilisée.
Il est possible de l'utiliser pour les tests A / B, les vues optionnelles ou pour réduire le
temps de chargement de l'application initiale.

import 'package:test/test.dart' deferred as test;

Nous verrons comment gérer l'asynchrone en Dart dans la leçon suivante. Ici, le
chargement de la librairie est asynchrone et nous ne pouvons pas l'utiliser
immédiatement.
Nous mettons un code d'exemple pour attendre le chargement de la librairie, mais les
notions seront abordées dans la leçon suivante :

Chapitre 2 : Les bases de Dart pour Flutter 41


import 'package:test/test.dart' deferred as test;

Future exectuerUneMethode() async {


await test.loadLibrary();
test.uneMethode();
}

Dans cet exemple, nous utilisons import 'package:test/test.dart' deferred as test; pour
importer la librairie de tests de manière différée et lui donner un alias test .
Ensuite, dans la fonction exectuerUneMethode() , nous utilisons await test.loadLibrary(); pour
charger la librairie de manière asynchrone. Une fois que la librairie est chargée, nous
pouvons appeler la méthode uneMethode() de la librairie test .

Notez que lorsque vous utilisez le chargement différé, vous devez utiliser await avant
d'appeler des éléments de la librairie chargée. Cela garantit que la librairie est chargée
et prête à être utilisée avant d'y accéder.
Le chargement différé est utile lorsque vous avez des parties de votre code qui ne sont
pas nécessaires au chargement initial de l'application, mais qui peuvent être chargées à
la demande. Cela peut contribuer à améliorer les performances et à réduire la taille de
l'application initiale.

L'encapsulation dans les librairies


Vous pouvez empêcher l'accès à un élément d'une librairie aux librairies l'important.
Pour ce faire il suffit de le préfixer avec _

// Dans la librairie 1 :
void _test() {
print("test");
}

// Dans la librairie 2
import 'test.dart' as test;
void main() {
test._test(); // Error
}

Exporter une librairie


Vous pouvez exporter une librairie depuis une librairie en utilisant export.

Chapitre 2 : Les bases de Dart pour Flutter 42


Cela peut être utile pour créer des index par exemple :

// soit un fichier tests.dart


export 'tests/test1.dart';
export 'tests/test2.dart';
export 'tests/test3.dart';

Vous pouvez ainsi importer directement les trois librairies en important tests.dart :

import 'tests.dart';

L'asynchrone
Dart propose de nombreuses fonctionnalités permettant de gérer l'asynchrone
facilement.
Les fonctions asynchrones retourne un résultat après une période de temps nécessaire
à une opération asynchrone : par exemple une requête HTTP.

Utilisation de async / await


En Dart, beaucoup de librairies retournent des éléments asynchrones qui sont appelés
Future.
Il est possible d'utiliser await sur un Future pour attendre la fin de son exécution.
L'utilisation est la même qu'en JavaScript / TypeScript, à savoir qu'il n'est possible
d'utiliser await que dans une fonction async.

await permet d'attendre le retour d'une fonction asynchrone, et permet donc de rendre
synchrone une exécution asynchrone.

Future attendreActionAsynchrone() async {


valeur = await actionAsynchrone();
// faire quelque chose avec valeur
}

Remarquez que le type retourné par une fonction est un Future, nous y reviendrons.

Vous pouvez rendre tout type de fonction asynchrone :

// Aussi bien la fonction main() :


Future main() async {
await actionAsynchrone();

Chapitre 2 : Les bases de Dart pour Flutter 43


}

// Que des fonctions fléchées :


Future actionAsynchrone() async => ...;

Gestion d'erreur
De même qu'en JavaScript, la gestion d'erreur des fonctions asynchrones se fait avec
des blocs try / catch, et éventuellement avec finally.

try {
valeur = await actionAsynchrone();
} catch (e) {
print(e);
}

Si une erreur survient dans l'exécution d'await, elle sera interceptée par catch et vous
pouvez la gérer comme vous le souhaitez dans le bloc catch.

Nous ne pouvons utiliser await que dans les fonctions asynchrones


mais nous pouvons utiliser try / catch partout.

Les Futures
Dart offre une API pour manipuler les Future autrement qu'avec async / await.

Depuis Dart 2.1, la librairie est incluse dans dart:core et il n'y a plus besoin de l'importer
avec dart:async.
Il faut privilégier l'utilisation d'async / await qui est plus lisible, mais nous vous
détaillons brièvement les deux méthodes utiles car vous pourriez les rencontrer dans
Flutter.
then() permet de prendre en argument une fonction qui reçoit la valeur retournée par le
Future et qui sera exécutée quand le Future aura terminé son exécution.
catchError() prend en paramètre une fonction qui reçoit l'erreur en argument et qui sera
exécutée dans le cas où l'exécution du Future rencontre une erreur,.
Future<T>.delayed(periode) permet de créer un Future qui s'exécutera après une
période passé en argument.
Prenons un exemple :

Chapitre 2 : Les bases de Dart pour Flutter 44


void main() {
actionAsync()
.then((value) => print(value))
.catchError((error) => print('Erreur'));
print('Valeur synchrone');
}

Future<String> actionAsync() {
return Future<String>.delayed(Duration(milliseconds: 2000),() => "V
}

Console
Valeur synchrone
Valeur asynchrone

Dans cet exemple, la fonction actionAsync() renvoie un Future qui se termine après une
période de 2000 millisecondes et retourne la valeur "Valeur asynchrone". Dans la
fonction main() , nous appelons actionAsync() et utilisons la méthode then() pour
spécifier une fonction qui sera exécutée lorsque le Future sera terminé. Cette fonction
prend la valeur retournée par le Future en argument et imprime cette valeur.

Nous utilisons également la méthode catchError() pour spécifier une fonction qui sera
exécutée si une erreur se produit lors de l'exécution du Future.
Enfin, nous imprimons "Valeur synchrone" pour illustrer que cette instruction est
exécutée de manière synchrone, tandis que l'exécution du Future est asynchrone.

Cependant, il est préférable d'utiliser les mots clés async et await chaque fois que cela
est possible, car ils offrent une syntaxe plus claire et permettent d'éviter des niveaux
d'imbrication excessifs lors de l'utilisation de plusieurs futures.

Chapitre 2 : Les bases de Dart pour Flutter 45

Vous aimerez peut-être aussi