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:

  1. class Point {
  2. num x, y;
  3. Point(num x, num y) {
  4. // There's a better way to do this, stay tuned.
  5. this.x = x;
  6. this.y = y;
  7. }
  8. }

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:

  1. class Point {
  2. num x, y;
  3. // Syntactic sugar for setting x and y
  4. // before the constructor body runs.
  5. Point(this.x, this.y);
  6. }

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:

  1. class Point {
  2. num x, y;
  3.  
  4. Point(this.x, this.y);
  5.  
  6. // Named constructor
  7. Point.origin() {
  8. x = 0;
  9. y = 0;
  10. }
  11. }

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:
  1. class Employee extends Person { Employee() : super.fromJson(defaultData); // ···}
Warning: Arguments to the superclass constructor do not have access to 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.
  1. // 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)');}
Warning: The right-hand side of an initializer does not have access to this.During development, you can validate inputs by using assert in theinitializer list.
  1. Point.withAssert(this.x, this.y) : assert(x >= 0) { print('In Point.withAssert(): ($x, $y)');}
Initializer lists are handy when setting up final fields. The following exampleinitializes three final fields in an initializer list. Click Run to executethe code.

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 (:).

  1. class Point {
  2. num x, y;
  3. // The main constructor for this class.
  4. Point(this.x, this.y);
  5. // Delegates to the main constructor.
  6. Point.alongXAxis(num x) : this(x, 0);
  7. }

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.

  1. class ImmutablePoint {
  2. static final ImmutablePoint origin =
  3. const ImmutablePoint(0, 0);
  4. final num x, y;
  5. const ImmutablePoint(this.x, this.y);
  6. }

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:

  1. class Logger {
  2. final String name;
  3. bool mute = false;
  4. // _cache is library-private, thanks to
  5. // the _ in front of its name.
  6. static final Map<String, Logger> _cache =
  7. <String, Logger>{};
  8. factory Logger(String name) {
  9. return _cache.putIfAbsent(
  10. name, () => Logger._internal(name));
  11. }
  12. Logger._internal(this.name);
  13. void log(String msg) {
  14. if (!mute) print(msg);
  15. }
  16. }

Note: Factory constructors have no access to this.

Invoke a factory constructor just like you would any other constructor:

  1. var logger = Logger('UI');
  2. logger.log('Button clicked');