Constructors in Depth

Implicit, no args Only if no other constructor is declared Point(this.x, this.y) Creates a new instance Multiple constructors with clear names : x = 0, y = 0 Runs before the body, sets final fields : this(x, 0) Delegates to another constructor const Point(...)

All fields final. Instances can be compile-time constants.

factory Logger(...) Can return existing instances or subtypes. No this access.

Forwards to the superclass constructor Library-private constructor (singletons, utility classes)

Initialization order: initializing formals and the initializer list → the superclass constructor → the constructor body.

class Point {
  final double x;
  final double y;

  // 1. Generative constructor with initializing formals
  Point(this.x, this.y);

  // 2. Named constructors
  Point.origin() : x = 0, y = 0;
  Point.fromJson(Map<String, dynamic> json)
      : x = (json['x'] as num).toDouble(),
        y = (json['y'] as num).toDouble();

  // 3. Initializer list with assert
  Point.positive(this.x, this.y) : assert(x >= 0 && y >= 0, 'Coordinates must be positive');

  // 4. Redirecting constructor
  Point.onXAxis(double x) : this(x, 0);

  @override
  String toString() => 'Point($x, $y)';
}

class ImmutablePoint {
  final int x, y;
  // 5. Const constructor: enables compile-time constant instances (canonicalized)
  const ImmutablePoint(this.x, this.y);
  static const origin = ImmutablePoint(0, 0);
}

class Logger {
  final String name;
  static final Map<String, Logger> _cache = {};

  // 6. Factory constructor: can return cached instances or subtypes
  factory Logger(String name) => _cache.putIfAbsent(name, () => Logger._internal(name));
  Logger._internal(this.name);
}

class Shape {
  // Factory returning subtypes
  factory Shape(String type) => switch (type) {
        'circle' => Circle(1),
 
…

12.1 Singleton Pattern

class AppConfig {
  AppConfig._();
  static final AppConfig instance = AppConfig._();
  String apiUrl = 'https://api.example.com';
}
AppConfig.instance.apiUrl;