Skip to content

Commit

Permalink
Clarify use of this in initializing instance variables (dart-lang#5310
Browse files Browse the repository at this point in the history
)

Co-authored-by: Marya <[email protected]>
Co-authored-by: Marya Belanger <[email protected]>
Co-authored-by: Erik Ernst <[email protected]>
Co-authored-by: Eric Windmill <[email protected]>
Co-authored-by: Eric Windmill <[email protected]>
Co-authored-by: Parker Lougheed <[email protected]>
  • Loading branch information
7 people authored and atsansone committed Jan 26, 2024
1 parent 9849e58 commit b81e491
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
16 changes: 16 additions & 0 deletions examples/misc/lib/language_tour/classes/point_this.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// ignore_for_file: invalid_reference_to_this, unnecessary_this
double initialX = 1.5;

class Point {
// OK, can access declarations that do not depend on `this`:
double? x = initialX;

// ERROR, can't access `this` in non-`late` initializer:
double? y = this.x;

// OK, can access `this` in `late` initializer:
late double? z = this.x;

// OK, `this.fieldName` is a parameter declaration, not an expression:
Point(this.x, this.y);
}
36 changes: 30 additions & 6 deletions src/language/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,16 @@ class Point {
}
```

All uninitialized instance variables have the value `null`.
An uninitialized instance variable declared with a
[nullable type][] has the value `null`.
Non-nullable instance variables [must be initialized][] at declaration.

All instance variables generate an implicit *getter* method.
Non-final instance variables and
`late final` instance variables without initializers also generate
an implicit *setter* method. For details,
check out [Getters and setters][].

If you initialize a non-`late` instance variable where it's declared,
the value is set when the instance is created,
which is before the constructor and its initializer list execute.
As a result, non-`late` instance variable initializers can't access `this`.

<?code-excerpt "misc/lib/language_tour/classes/point_with_main.dart (class+main)" replace="/(double .*?;).*/$1/g" plaster="none"?>
```dart
class Point {
Expand All @@ -195,6 +192,31 @@ void main() {
}
```

Initializing a non-`late` instance variable where it's declared
sets the value when the instance is created,
before the constructor and its initializer list execute.
As a result, the initializing expression (after the `=`)
of a non-`late` instance variable can't access `this`.

<?code-excerpt "misc/lib/language_tour/classes/point_this.dart"?>
```dart
double initialX = 1.5;
class Point {
// OK, can access declarations that do not depend on `this`:
double? x = initialX;
// ERROR, can't access `this` in non-`late` initializer:
double? y = this.x;
// OK, can access `this` in `late` initializer:
late double? z = this.x;
// OK, `this.fieldName` is a parameter declaration, not an expression:
Point(this.x, this.y);
}
```

Instance variables can be `final`,
in which case they must be set exactly once.
Initialize `final`, non-`late` instance variables
Expand Down Expand Up @@ -350,3 +372,5 @@ can pass a static method as a parameter to a constant constructor.
[initializer list]: /language/constructors#initializer-list
[factory constructor]: /language/constructors#factory-constructors
[late-final-ivar]: /effective-dart/design#avoid-public-late-final-fields-without-initializers
[nullable type]: /null-safety/understanding-null-safety#using-nullable-types
[must be initialized]: /null-safety/understanding-null-safety#uninitialized-variables

0 comments on commit b81e491

Please sign in to comment.