Implémentation des Patterns Dart
Sommaire
- Stratégie de sélection de patterns
- Switch statements vs. expressions
- Implémentations de patterns fondamentaux
- Workflows
- Exemples
Stratégie de sélection de patterns
Applique des types de patterns spécifiques en fonction de la structure des données et du résultat souhaité. Suis ces directives conditionnelles :
- Si tu valides et extrais depuis des données désérialisées (ex. JSON) : Utilise les patterns Map et List pour vérifier simultanément la structure et destructurer les paires clé-valeur.
- Si tu gères plusieurs valeurs de retour : Utilise les patterns Record pour destructurer les champs directement en variables locales.
- Si tu exécutes un comportement spécifique au type (Algebraic Data Types) : Utilise les patterns Object combinés avec les classes
sealedpour assurer l'exhaustivité. - Si tu fais correspondre des plages numériques ou des conditions : Utilise les patterns Relationnels (
>=,<=) et Logical-and (&&). - Si plusieurs cas partagent la même logique : Utilise les patterns Logical-or (
||) pour partager un seul corps de cas ou une clause guard. - Si tu ignores certaines valeurs : Utilise le pattern Wildcard (
_) ou un élément Rest sans correspondance (...) dans les collections.
Switch statements vs. expressions
Sélectionne la construction switch appropriée en fonction du contexte d'exécution :
- Si tu produis une valeur : Utilise une switch expression.
- Syntaxe :
switch (value) { pattern => expression, } - Règle : Chaque cas doit être une seule expression. Pas de fallthrough implicite. Doit être exhaustive.
- Syntaxe :
- Si tu exécutes des statements ou des effets de bord : Utilise un switch statement.
- Syntaxe :
switch (value) { case pattern: statements; } - Règle : Les cas vides passent au cas suivant. Les cas non-vides font un break implicite (aucun mot-clé
breakrequis).
- Syntaxe :
Implémentations de patterns fondamentaux
Implémente les patterns en utilisant la syntaxe et les règles suivantes :
- Logical-or (
||) :pattern1 || pattern2. Les deux branches doivent définir exactement le même ensemble de variables. - Logical-and (
&&) :pattern1 && pattern2. Les branches ne doivent pas définir de variables chevauchantes. - Relationnel :
==,!=,<,>,<=,>=suivis d'une expression constante. - Cast (
as) :pattern as Type. Lève une exception si la valeur ne correspond pas au type. À utiliser pour affirmer fortement les types lors de la destructuration. - Null-check (
?) :pattern?. Échoue la correspondance si la valeur est null. Lie la variable au type de base non-nullable. - Null-assert (
!) :pattern!. Lève une exception si la valeur est null. - Variable :
var nameouType name. Lie la valeur correspondante à une nouvelle variable locale. - Wildcard (
_) : Correspond à n'importe quelle valeur et l'ignore. - List :
[pattern1, pattern2]. Correspond à des listes de longueur exacte à moins qu'un élément Rest (...ou...var rest) soit utilisé. - Map :
{"key": pattern}. Correspond à des maps contenant les clés spécifiées. Ignore les clés non correspondantes. - Record :
(pattern1, named: pattern2). Correspond à des records de la forme exacte. Utilise:var namepour inférer le nom du getter. - Object :
ClassName(field: pattern). Correspond à des instances deClassName. Utilise:var fieldpour inférer le nom du getter.
Workflows
Progression des tâches : Implémentation du Pattern Matching
Copie cette checklist pour suivre la progression lors de l'implémentation d'une logique de pattern matching complexe :
- [ ] Identifie la structure de données évaluée (JSON, Record, Class, Enum).
- [ ] Sélectionne la construction switch appropriée (Expression pour les valeurs, Statement pour les effets de bord).
- [ ] Définis les patterns requis (Object, Map, List, Record).
- [ ] Extrais les données requises en utilisant les patterns Variable (
var x,:var y). - [ ] Applique des clauses guard (
when condition) pour la logique qui ne peut pas être exprimée via les patterns. - [ ] Gère les cas non correspondants en utilisant un Wildcard (
_) ou une clausedefault(si tu n'utilises pas une classe sealed). - [ ] Lance le validateur d'exhaustivité.
Boucle de feedback : Vérification de l'exhaustivité
Lorsque tu fais une correspondance sur des classes sealed ou des enums, tu dois assurer que tous les sous-types sont gérés.
- Lance le validateur : Exécute
dart analyze. - Revois les erreurs : Cherche les erreurs "The type 'X' is not exhaustively matched by the switch cases".
- Corrige : Ajoute les patterns Object manquants pour les sous-types non gérés, ou ajoute un cas Wildcard (
_) si un fallback par défaut est acceptable.
Exemples
Validation et Destructuring JSON
Utilise les patterns Map et List pour valider la structure et extraire les données en une seule étape.
Input :
var data = {
'user': ['Lily', 13],
};
Implémentation :
if (data case {'user': [String name, int age]}) {
print('User $name is $age years old.');
} else {
print('Invalid JSON structure.');
}
Algebraic Data Types (Sealed Classes)
Utilise les patterns Object avec les switch expressions pour gérer exhaustivement les types familliaux.
Implémentation :
sealed class Shape {}
class Square implements Shape {
final double length;
Square(this.length);
}
class Circle implements Shape {
final double radius;
Circle(this.radius);
}
// La switch expression garantit l'exhaustivité grâce au modificateur `sealed`.
double calculateArea(Shape shape) => switch (shape) {
Square(length: var l) => l * l,
Circle(:var radius) => math.pi * radius * radius,
};
Échange et Destructuring de variables
Utilise les patterns d'assignation de variables pour échanger des valeurs ou extraire des champs record sans variables temporaires.
Implémentation :
var (a, b) = ('left', 'right');
(b, a) = (a, b); // Swap values
// Destructuring d'une fonction de retour
var (name, age) = getUserInfo();
Clauses Guard et Logical-or
Utilise when pour évaluer des conditions arbitraires après qu'un pattern correspond.
Implémentation :
switch (shape) {
case Square(size: var s) || Circle(size: var s) when s > 0:
print('Valid symmetric shape with size $s');
case Square() || Circle():
print('Invalid or empty shape');
default:
print('Unknown shape');
}