tezvyn:

Dart's Specialized Constructors: Named, Factory, and Constant

AI-drafted, machine-checkedSource: dart.devintermediate

Dart constructors offer more than one way to create an object. Use named constructors for clarity (e.g., fromJSON), factory for caching or returning subtypes, and const for compile-time constant objects.

WHY IT EXISTS A single, default constructor is often too restrictive for real-world applications. Systems need to create objects from different data sources like JSON, manage object creation to save memory through caching, or guarantee immutability for performance. Dart's specialized constructors solve these problems directly.

THE MENTAL MODEL Think of constructors as different ways to get a car. The default constructor is buying a new car off the assembly line. A named constructor, Car.fromScrap(), is building one from salvaged parts—a different process for the same result. A factory constructor is like a dispatcher: you ask for 'a ride' and they might send a new car, a used one from their fleet, or even a motorcycle (a subtype). A const constructor is like a perfect, unchangeable model car on your shelf, created once and reused forever.

HOW IT WORKS NAMED: A constructor with an extra identifier, like ClassName.identifierName(). It always creates a new instance and is used to clarify the object's origin or purpose, such as Point.fromPolarCoordinates().

FACTORY: Declared with the factory keyword. It doesn't have access to this and must explicitly return an object. This allows it to return a cached instance, an instance of a subtype, or a new instance after some logic. It decouples the requested type from the actual object returned.

CONSTANT: Declared with the const keyword. All instance variables must be final. It creates a compile-time constant. If you create two identical const objects, Dart reuses the same canonical instance, saving memory and enabling performance optimizations.

WHEN TO USE IT Use a named constructor for multiple, distinct creation pathways, like User.fromJSON(). Use a factory constructor to implement a singleton pattern, return an instance from a cache, or return a subclass instance based on input. Use a const constructor for immutable value-like objects, which is critical for performance in Flutter widgets.

WHEN NOT TO USE IT Don't overuse named constructors for minor variations where optional parameters on a default constructor would be cleaner. Avoid factories when you just need a new instance; a regular constructor is more direct. You cannot use a const constructor if any instance variable is not final or if the constructor performs logic beyond initialization.

ONE CANONICAL EXAMPLE A Logger class can combine these. A factory Logger(String name) constructor can check a cache for an existing logger with that name. If found, it returns the cached instance; otherwise, it calls a private named constructor Logger._internal(name) to create, cache, and return a new one. This ensures only one logger instance exists per name, a common singleton pattern. A separate named constructor, Logger.fromJson(data), could initialize the logger from a configuration map.

Read the original → dart.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.