Champs Final & Const
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 18 sur 110.
Lors de la déclaration de champs dans une classe, vous pouvez utiliser final ou const pour contrôler si les valeurs peuvent changer après l'initialisation. Les deux créent des valeurs immuables, mais ils fonctionnent différemment.
Un champ final ne peut être défini qu'une seule fois, mais sa valeur est déterminée à l'exécution. Vous pouvez l'assigner lors de la déclaration ou via un constructeur :
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}
Person p = Person('Alice');
// p.name = 'Bob'; // Erreur : impossible de réassigner un champ finalLe name est défini lors de la création de l'objet, et createdAt capture l'heure actuelle. Les deux valeurs sont verrouillées après l'initialisation.
Un champ static const doit avoir une valeur connue au moment de la compilation. Il appartient à la classe elle-même et est partagé entre toutes les instances :
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}La différence clé : les champs final peuvent contenir des valeurs calculées au moment de l'exécution (comme DateTime.now()), alors que const nécessite des constantes au moment de la compilation. Les champs d'instance ne peuvent pas être const directement - seul static const est autorisé au niveau de la classe.
Défi
FacileConstruisons un système de catalogue de produits qui démontre la différence entre les champs final et static const. Vous allez créer des produits avec des propriétés immuables et des valeurs de configuration partagées.
Vous organiserez votre code en deux fichiers :
product.dart: Définissez une classeProductqui représente un article dans un magasin. Votre classe doit avoir :- Un
static const double taxRatedéfini à0.08(taux de taxe de 8 % partagé par tous les produits) - Un
static const String currencydéfini à'USD' - Un
final String namepour le nom du produit (défini via le constructeur) - Un
final double basePricepour le prix de base du produit (défini via le constructeur) - Un
final String sku(unité de gestion des stocks) qui combine un préfixe avec le nom du produit, calculé dans une liste d'initialisation comme'SKU-'suivi du nom en majuscules - Un constructeur qui prend
nameetbasePrice - Un getter
priceWithTaxqui calcule le prix incluant la taxe - Une méthode
display()qui affiche les informations du produit
- Un
main.dart: Importez votre classe de produit et créez deux produits :- Un
'Laptop'avec un prix de base de999.99 - Un
'Mouse'avec un prix de base de29.99
display()sur chaque produit dans l'ordre listé ci-dessus.- Un
La méthode display() doit afficher les informations exactement dans ce format :
[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])Arrondissez priceWithTax à 2 décimales en utilisant toStringAsFixed(2) lors de l'affichage.
Sortie attendue :
SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)Aide-mémoire
Utilisez final pour les champs qui sont définis une seule fois à l'exécution et qui ne peuvent plus être modifiés par la suite. Utilisez static const pour les constantes de compilation partagées par toutes les instances d'une classe.
Les champs final sont définis à l'exécution et peuvent être initialisés lors de la déclaration ou dans le constructeur :
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}Les champs static const doivent avoir des valeurs constantes à la compilation et appartiennent à la classe elle-même :
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}Vous pouvez calculer les valeurs des champs final dans une liste d'initialisation :
class Product {
final String name;
final String sku;
Product(this.name) : sku = 'SKU-${name.toUpperCase()}';
}Différences clés :
final: Valeurs à l'exécution, peuvent être différentes pour chaque instancestatic const: Constantes à la compilation, partagées par toutes les instances- Les champs d'instance ne peuvent pas être
constdirectement - seulstatic constest autorisé
Essayez vous-même
import 'product.dart';
void main() {
// TODO: Créer un Product appelé 'Laptop' avec un prix de base de 999.99
// TODO: Créer un Product appelé 'Mouse' avec un prix de base de 29.99
// TODO: Appeler display() sur chaque produit dans l'ordre (Laptop d'abord, puis Mouse)
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository