Constructors
Declare a constructor by creating a function with the same name as itsclass (plus, optionally, an additional identifier as described inNamed constructors).The most common form of constructor, the generative constructor, createsa new instance of a class:
class Point {
num x, y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
The this
keyword refers to the current instance.
Note: Use this
only when there is a name conflict. Otherwise, Dart style omits the this
.
The pattern of assigning a constructor argument to an instance variableis so common, Dart has syntactic sugar to make it easy:
class Point {
num x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
Default constructors
If you don’t declare a constructor, a default constructor is providedfor you. The default constructor has no arguments and invokes theno-argument constructor in the superclass.
Constructors aren’t inherited
Subclasses don’t inherit constructors from their superclass. A subclassthat declares no constructors has only the default (no argument, noname) constructor.
Named constructors
Use a named constructor to implement multiple constructors for a classor to provide extra clarity:
- class Point {
- num x, y;
- Point(this.x, this.y);
- // Named constructor
- Point.origin() {
- x = 0;
- y = 0;
- }
- }
Remember that constructors are not inherited, which means that asuperclass’s named constructor is not inherited by a subclass. If youwant a subclass to be created with a named constructor defined in thesuperclass, you must implement that constructor in the subclass.
Invoking a non-default superclass constructor
By default, a constructor in a subclass calls the superclass’s unnamed,no-argument constructor.The superclass’s constructor is called at the beginning of theconstructor body. If an initializer listis also being used, it executes before the superclass is called.In summary, the order of execution is as follows:
- initializer list
- superclass’s no-arg constructor
- main class’s no-arg constructorIf the superclass doesn’t have an unnamed, no-argument constructor,then you must manually call one of the constructors in thesuperclass. Specify the superclass constructor after a colon (
:
), justbefore the constructor body (if any).
In the following example, the constructor for the Employee class calls the namedconstructor for its superclass, Person. Click Run to execute the code.
Because the arguments to the superclass constructor are evaluated beforeinvoking the constructor, an argument can be an expression such as afunction call:Warning: Arguments to the superclass constructor do not have access to
class Employee extends Person { Employee() : super.fromJson(defaultData); // ···}
this
. For example, arguments can call static methods but not instance methods.#### Initializer listBesides invoking a superclass constructor, you can also initializeinstance variables before the constructor body runs. Separateinitializers with commas.Warning: The right-hand side of an initializer does not have access to
// Initializer list sets instance variables before// the constructor body runs.Point.fromJson(Map<String, num> json) : x = json['x'], y = json['y'] { print('In Point.fromJson(): ($x, $y)');}
this
.During development, you can validate inputs by using assert
in theinitializer list.Initializer lists are handy when setting up final fields. The following exampleinitializes three final fields in an initializer list. Click Run to executethe code.
- Point.withAssert(this.x, this.y) : assert(x >= 0) { print('In Point.withAssert(): ($x, $y)');}
Redirecting constructors
Sometimes a constructor’s only purpose is to redirect to anotherconstructor in the same class. A redirecting constructor’s body isempty, with the constructor call appearing after a colon (:).
class Point {
num x, y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
Constant constructors
If your class produces objects that never change, you can make theseobjects compile-time constants. To do this, define a const
constructorand make sure that all instance variables are final
.
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
Constant constructors don’t always create constants.For details, see the section onusing constructors.
Factory constructors
Use the factory
keyword when implementing a constructor that doesn’talways create a new instance of its class. For example, a factoryconstructor might return an instance from a cache, or it might return aninstance of a subtype.
The following example demonstrates a factory constructor returningobjects from a cache:
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name));
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
Note: Factory constructors have no access to this
.
Invoke a factory constructor just like you would any other constructor:
var logger = Logger('UI');
logger.log('Button clicked');