Human-Powered Random Text Generator

Random thoughts by Yu Asakusa

Initializing the same variable twice in Dart

18 Jan 2014

I recently started learning programming language Dart, and realized that according to the wording of the language specification, it is possible to initialize some variables twice in Dart. And I am not confusing initialization with assignment.

I am referring to the language spec 1.1, although I do not think that the relevant part has changed since language spec 1.0.

This happens because an instance variable of a class can have an initializer in its declaration, and a constructor of that class can contain an initializer for the same instance variable in its initializer list (after a colon).

Consider the following Dart code.

// Program 1

class C {
  int x = 10;    // first initializer
  C() : x = 20;  // second initializer
}

main() {
  print((new C()).x); // => 20
}

In the code, there are two initializers which tell how instance variable x is initialized:

  1. Instance variable declaration int x = 10 contains initializer = 10.
  2. Constructor C() contains initializer x = 20 in its initializer list. (Note that x = 20 here is not an assignment expression.)

This code prints 20, which is the result of the second initializer. But this is not because the existence of the second initializer prevents the initialization specified by the first initializer. Rather, according to the language spec, x is initialized to 10 first as stated in the section about the new expression, and then the second initializer initializes x to 20 as stated in the section about the initializer list of a constructor. Therefore, the output of the program is a result of the second initializer having overwritten the result of the first initializer.

I cannot come up with a way to observe the fact that x is actually initialized twice, and there may well be no such way. However, it is easy to observe that the expression in the first initializer is evaluated:

// Program 2

class C {
  int x = 100 ~/ 0; // when evaluated, this will throw
                    // IntegerDivisionByZeroException
  C() : x = 20;
}

main() {
  print((new C()).x); // Unhandled exception: IntegerDivisionByZeroException
}

This does not look like an oversight in the spec, because the spec explicitly states that it is a runtime error if a final instance variable is initialized by both the variable declaration and an initializer in a constructor (see also issue 12539 of Dart).

Although it does not seem to cause any real harm, I find it unintuitive that some variables are initialized twice. I have no idea why the spec defines the behavior this way, particularly given that the effect of the first initialization does not seem visible except that evaluation of the expression in the first initializer may have a side effect and that the first initialization causes the second initialization to be a runtime error in the case of final variables.

I am not sure if it is worth, but there are at least two ways to modify the language spec so that no variables are initialized more than once: