Difference between assigning the values in parameter list and initializer list

Dart constructs objects in two phases: first outside-in and then inside-out.

Initializer lists are executed outside-in (from derived class to base class). After this is done, the object’s members should be initialized, the object is considered to be “constructed”, and this exists. (That’s why you can’t use this in a meaningful way in an initializer list; it doesn’t exist yet.) (Technically direct member initialization occurs before initializer lists, but I’m lumping them together for simplicity.)

Constructor bodies are then executed inside-out (from base class to derived class).

This approach guarantees that all of the object’s members are initialized when the base class constructor body executes, allowing virtual dispatch to occur in the constructor body. (In contrast, C++ constructs objects purely inside-out and disallows virtual dispatch in constructors and destructors. Or contrast to Java where, IIRC, the class mostly defines its own construction order, and the classes are responsible to ensure that any virtual function calls performed by the constructor are safe.)

Without this approach, a Dart constructor body either cannot guarantee safety when executing virtual functions (the Java approach) or must disallow virtual dispatch (the C++ approach).

One consequence of this approach is that final variables can be initialized by initializer lists but not by constructor bodies: when the constructor body executes, all member variables (that aren’t late and that aren’t nullable) are expected to be initialized already.

Also see:

Leave a Comment