Qu’est-ce qu’un constructeur
Un constructeur est une fonction spéciale servant à créer des instances de classe, généralement chargée d’initialiser les propriétés. À l’exception du constructeur par défaut, tous les constructeurs portent le même nom que la classe.
Classification des constructeurs Dart :
- Constructeur génératif (Generative)
- Constructeur par défaut (Default)
- Constructeur nommé (Named)
- Constructeur constant (Const)
- Constructeur de redirection (Redirecting)
- Constructeur usine (Factory)
- Constructeur usine de redirection
- Syntaxe de constructeur concise (Dart 3.13+)
- Constructeur principal (Primary Constructors, champs minimalistes + syntaxe constructeur)
1. Constructeur génératif Generative Constructor
Constructeur de base, il crée des instances et initialise les variables membres. Il prend en charge les paramètres d’initialisation this.variable qui simplifient l’affectation.
class Point {
double x;
double y;
// Constructeur génératif, this.x reçoit directement le paramètre pour affecter le membre
Point(this.x, this.y); // Affecte directement des valeurs à x et y
}
void main() {
final p = Point(10, 20);
print("(${p.x}, ${p.y})"); // (10, 20)
}
Langage du code : JavaScript (javascript)
2. Constructeur par défaut Default Constructor
Si aucune fonction constructeur n’est définie manuellement dans une classe, Dart fournit automatiquement un constructeur génératif sans paramètres et sans nom. Ce fonctionnement est identique aux autres langages de type C comme C++, Java, C#, etc.
class PointA {
double x = 0;
double y = 0;
// Constructeur par défaut implicite : PointA();
}
void main() {
final p = PointA(); // Appel automatique du constructeur par défaut
print("(${p.x}, ${p.y})"); // (0.0, 0.0)
}
Langage du code : PHP (php)
Attention : dès que vous écrivez manuellement un constructeur quelconque, le constructeur par défaut disparaît.
3. Constructeur nommé Named Constructor
Rôle : définir plusieurs constructeurs dans une même classe avec une sémantique claire ; format NomClasse.NomConstructeur()
const double xOrigin = 0;
const double yOrigin = 0;
class Point {
final double x;
final double y;
// Constructeur génératif principal
Point(this.x, this.y);
// Constructeur nommé : point d'origine
Point.origin() : x = xOrigin, y = yOrigin;
}
void main() {
final p1 = Point(5, 6);
final p2 = Point.origin(); // Appel du constructeur nommé
print(p1.x); //5
print("Point d'origine : (${p2.x}, ${p2.y})"); // (0,0)
}
Langage du code : PHP (php)
Règles essentielles
- Les sous-classes n’héritent pas des constructeurs nommés de la classe parent ; si vous avez besoin d’un constructeur nommé identique dans la sous-classe, vous devez l’implémenter manuellement ;
- Les constructeurs nommés prennent en charge la liste d’initialisation pour affecter des valeurs aux variables final.
4. Constructeur constant Const Constructor
Utilisé pour créer des objets constants à la compilation, conditions requises :
- Toutes les variables membres doivent être marquées
final - Ajoutez le mot-clé
constau constructeur ; utilisezconstlors de l’instanciation pour réutiliser le cache des constantes. Si vous omettez const, une instance ordinaire sera créée.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0); // Statique appartenant à la classe, partagé par toute la classe
final double x, y;
// Le constructeur constant peut initialiser x et y déclarés final
const ImmutablePoint(this.x, this.y);
}
void main() {
// Constante de compilation, réutilisation du même objet
const p1 = ImmutablePoint(1, 2);
const p2 = ImmutablePoint(1, 2); // Les paramètres transmis doivent être identiques, sinon ce sont des objets distincts
print(p1 == p2); // true
// Instance ordinaire, nouvel objet
final p3 = ImmutablePoint(1, 2);
print(p1 == p3); // false
}Langage du code : PHP (php)
5. Constructeur de redirection Redirecting Constructor
Constructeur qui transfère l’exécution vers un autre constructeur de la même classe avec la syntaxe : this(paramètres), le corps de la fonction doit être vide.
class Point {
double x, y;
// Constructeur principal
Point(this.x, this.y);
// Constructeur de redirection : ne transmet que x, y fixé à 0, renvoie vers le constructeur principal
Point.alongX(double x) : this(x, 0); // Appelle le constructeur nommé puis transmet x au constructeur principal tout en affectant y=0
}
void main() {
final p = Point.alongX(9);
print("x=${p.x}, y=${p.y}"); // x=9, y=0
}
Langage du code : JavaScript (javascript)
6. Constructeur usine Factory Constructor
Mot-clé factory, cas d’utilisation adaptés :
- Ne crée pas systématiquement un nouvel objet (réutilisation du cache, renvoi d’instances de sous-classe)
- Logique complexe avant construction (analyse JSON, validation des paramètres). Restriction : impossible d’accéder à
this
Exemple de singleton Logger avec cache
class Logger {
final String name;
bool mute = false;
// Cache privé visible uniquement dans la bibliothèque
static final Map<String, Logger> _cache = {};
// Constructeur usine : récupère d'abord depuis le cache
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
// Constructeur usine : créer à partir de l'analyse json
factory Logger.fromJson(Map<String, dynamic> json) {
return Logger(json["name"].toString());
}
// Constructeur génératif interne privé
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
void main() {
final log1 = Logger("UI");
final log2 = Logger("UI");
print(log1 == log2); // true, même objet du cache
final jsonLog = Logger.fromJson({"name": "Net"});
jsonLog.log("request success");
}
Langage du code : JavaScript (javascript)
7. Constructeur usine de redirection Redirecting Factory
Syntaxe factory Nom() = ConstructeurAutreClasse;, adapté aux classes abstraites qui délèguent la création d’instances, évite de redéfinir les paramètres à plusieurs reprises.
abstract class Listenable {}
class _MergingListenable implements Listenable {
List<_MergingListenable> list;
_MergingListenable(this.list);
}
// Usine de redirection, appelle le constructeur de la classe privée interne
factory Listenable.merge(List<Listenable> list) = _MergingListenable;
Langage du code : PHP (php)
8. Détachement de constructeur Constructor Tear-offs
Passez directement le constructeur en argument de fonction sans écrire (), remplace les fonctions anonymes lambda redondantes pour de meilleures performances.
Écriture recommandée
void main() {
final charCodes = [65, 66, 67];
// Constructeur nommé String.fromCharCode
final strs = charCodes.map(String.fromCharCode);
print(strs); // (A, B, C)
// Détachement de constructeur sans nom avec .new
final buffers = charCodes.map(StringBuffer.new);
}
Langage du code : PHP (php)
Non recommandé : lambda superflu
// Encapsulation inutile, à éviter
charCodes.map((code) => String.fromCharCode(code));
Langage du code : JavaScript (javascript)
9. Syntaxe de constructeur concise (Dart 3.13+) Concise Constructor
À l’intérieur de la classe, vous pouvez omettre le nom de la classe, utilisez directement new / factory pour définir les constructeurs sans écrire NomClasse.xxx :
| Syntaxe traditionnelle | Raccourci |
|---|---|
Point(this.x,this.y) | new(this.x,this.y) |
Point.origin():x=0,y=0 | new origin():x=0,y=0 |
factory Point.clone() | factory clone() |
class Point {
double x, y;
// Constructeur génératif sans nom raccourci
new(this.x, this.y);
// Constructeur génératif nommé raccourci
new origin() : x = 0, y = 0;
// Constructeur usine raccourci
factory clone(Point other) => new(other.x, other.y);
}
void main() {
final p = new(3, 4);
final origin = new origin();
final copy = p.clone(p);
}
Langage du code : PHP (php)
10. Trois manières d’initialiser les variables d’instance
1 : Affectation directe à la déclaration
class PointA {
double x = 1.0;
double y = 2.0;
}
Langage du code : JavaScript (javascript)
2 : Paramètres d’initialisation
this.variable
Prend en charge les paramètres positionnels optionnels, paramètres nommés et variables nullables
class PointB {
final double x;
final double y;
// Paramètres positionnels optionnels
PointB.opt([this.x = 0, this.y = 0]);
// Paramètres nommés avec valeur par défaut
PointB.named({this.x = 5, this.y = 5});
}
Langage du code : JavaScript (javascript)
3 : Liste d’initialisation Initializer List
Affectation après le deux-points :, s’exécute avant le corps du constructeur, ne peut pas accéder à this, prend en charge assert pour la validation des paramètres.
class Point {
final double x;
final double y;
Point.fromJson(Map<String, double> json)
: x = json["x"]!,
y = json["y"]! {
print("Corps du constructeur exécuté, x=$x");
}
// Avec validation par assertion
Point.withAssert(this.x, this.y) : assert(x >= 0);
}
Langage du code : JavaScript (javascript)
11. Paramètres d’initialisation directs des champs privés (Dart3.12+)
Pour les variables privées préfixées d’un underscore, écrivez les paramètres du constructeur sous la forme this._champ ; lors de l’appel externe, utilisez directement le nom public sans underscore.
class Point {
final double _x;
final double _y;
// Interne _x, appel externe s'écrit x:10
Point({required this._x, this._y = 0});
}
void main() {
final p = Point(x: 10); // Pas besoin d'écrire _x, directement x
print(p._x); // 10
}
Langage du code : PHP (php)
Utilisez le nom d’origine de la variable privée dans la liste d’initialisation :
class Point {
final double _x;
Point({required this._x}) : assert(_x > 0);
}
Langage du code : JavaScript (javascript)
12. Constructeurs de la classe parent et règles d’héritage
- Les sous-classes n’héritent d’aucun constructeur de la classe parent ;
- Ordre d’exécution du constructeur : liste d’initialisation → constructeur parent → corps du constructeur de la sous-classe ;
- Si la classe parent ne dispose pas de constructeur par défaut sans paramètres, la sous-classe doit appeler manuellement
super()pour désigner le constructeur parent.
Exemple d’appel super basique
Comme en Java, on utilise super pour désigner la classe de base ; en C#, on utilise base.
class Person {
final String name;
Person(this.name);
Person.fromMap(Map map) : name = map["name"];
}
class Employee extends Person {
int id;
// Appel du constructeur nommé de la classe parent
Employee(Map data) : super.fromMap(data), id = data["id"];
}
Langage du code : JavaScript (javascript)
Attention : l’expression des paramètres de super ne peut pas utiliser
this.
Paramètres Super (Dart2.17+, simplifie la transmission des paramètres au parent)
Utilisez super.variable pour transmettre directement les paramètres au constructeur parent sans écrire manuellement super(x,y)
class Vector2d {
final double x, y;
Vector2d(this.x, this.y);
}
class Vector3d extends Vector2d {
final double z;
// super.x super.y transmettent automatiquement vers le constructeur parent
Vector3d(super.x, super.y, this.z);
}
// Constructeur nommé parent + paramètres nommés super
class Vector3dYZ extends Vector2d {
final double z;
Vector3dYZ({required super.y, required this.z}) : super.named(x: 0);
}
Langage du code : JavaScript (javascript)