Constructors
Default constructors, named constructors, initializer lists, and factory constructors.
3 menit membaca
A constructor is the function Dart calls to build a new instance of a class. You've already seen the shorthand form; this lesson covers the rest of what constructors can do.
The default constructor and field shorthand
class Point {
double x;
double y;
Point(this.x, this.y);
}
final p = Point(3.0, 4.0);Point(this.x, this.y) is equivalent to writing Point(double x, double y) { this.x = x; this.y = y; } — Dart lets you skip the body entirely for the common case of "just assign each parameter to a field of the same name."
Named constructors
A class can have more than one constructor, as long as only one is unnamed. Named constructors give you multiple, clearly-labeled ways to build the same type:
class Point {
double x;
double y;
Point(this.x, this.y);
Point.origin() : x = 0, y = 0;
Point.fromList(List<double> coordinates)
: x = coordinates[0],
y = coordinates[1];
}
final a = Point(3, 4);
final b = Point.origin();
final c = Point.fromList([5, 6]);The : x = 0, y = 0 syntax is an initializer list — it runs before the constructor body and is the required place to set final fields that don't come directly from a constructor parameter. Named constructors are Dart's answer to a problem other languages solve with overloading: instead of several same-named constructors distinguished only by parameter types, each one gets a name that says what it does.
Initializer lists and validation
Initializer lists can also run assertions, which is useful for catching invalid data the moment an object is constructed rather than later:
class Temperature {
final double celsius;
Temperature(this.celsius) : assert(celsius >= -273.15, 'Below absolute zero');
}Constant constructors
If every field of a class is final, you can mark the constructor const, which allows creating compile-time constant instances:
class ImmutablePoint {
final double x;
final double y;
const ImmutablePoint(this.x, this.y);
}
const origin = ImmutablePoint(0, 0);Two const instances built with identical arguments are actually the same object in memory — Dart deduplicates them automatically. This matters most in Flutter, where const widgets can skip being rebuilt entirely, but it's a useful pattern for any genuinely immutable value in plain Dart too.
Factory constructors
A factory constructor doesn't have to return a new instance at all — it can return an existing one, or an instance of a subclass, based on logic you control:
class Logger {
static final Logger _instance = Logger._internal();
factory Logger() {
return _instance;
}
Logger._internal();
void log(String message) => print('[LOG] $message');
}
void main() {
final logger1 = Logger();
final logger2 = Logger();
print(identical(logger1, logger2)); // true — same instance both times
}Logger._internal() is a named constructor prefixed with an underscore, making it private to this file — callers can't bypass the factory and construct a second instance directly. This is the classic singleton pattern: factory Logger() always hands back the one shared _instance instead of building a new object each time.
Between default, named, const, and factory constructors, Dart gives you enough flexibility to express almost any object-creation rule directly in the type itself, rather than scattering validation and setup logic across the rest of your codebase.