From 0e192d51daf83644b97023652417a57dfcbe14e6 Mon Sep 17 00:00:00 2001 From: Tony Sansone Date: Fri, 12 Apr 2024 12:50:18 -0500 Subject: [PATCH 1/3] Updated constructors page --- .../lib/language_tour/classes/employee.dart | 4 +- .../classes/immutable_point.dart | 4 +- .../lib/language_tour/classes/logger.dart | 4 +- .../misc/lib/language_tour/classes/point.dart | 8 +- .../classes/point_redirecting.dart | 4 +- .../classes/point_with_distance_field.dart | 7 +- .../classes/super_initializer_parameters.dart | 4 +- src/content/language/constructors.md | 86 ++++++++----------- 8 files changed, 50 insertions(+), 71 deletions(-) diff --git a/examples/misc/lib/language_tour/classes/employee.dart b/examples/misc/lib/language_tour/classes/employee.dart index d7efe0687c..8879c696c2 100644 --- a/examples/misc/lib/language_tour/classes/employee.dart +++ b/examples/misc/lib/language_tour/classes/employee.dart @@ -4,11 +4,11 @@ Map fetchDefaultData() => {}; // stub // #docregion super class Person { - String? firstName; - Person.fromJson(Map data) { print('in Person'); } + + String? firstName; } // #docregion method-then-constructor diff --git a/examples/misc/lib/language_tour/classes/immutable_point.dart b/examples/misc/lib/language_tour/classes/immutable_point.dart index 813c608611..81bb1402fd 100644 --- a/examples/misc/lib/language_tour/classes/immutable_point.dart +++ b/examples/misc/lib/language_tour/classes/immutable_point.dart @@ -1,7 +1,7 @@ class ImmutablePoint { static const ImmutablePoint origin = ImmutablePoint(0, 0); - final double x, y; - const ImmutablePoint(this.x, this.y); + + final double x, y; } diff --git a/examples/misc/lib/language_tour/classes/logger.dart b/examples/misc/lib/language_tour/classes/logger.dart index 734288fb2d..60a87fbf4d 100644 --- a/examples/misc/lib/language_tour/classes/logger.dart +++ b/examples/misc/lib/language_tour/classes/logger.dart @@ -1,5 +1,7 @@ // #docregion constructors class Logger { + Logger._internal(this.name); + final String name; bool mute = false; @@ -15,8 +17,6 @@ class Logger { return Logger(json['name'].toString()); } - Logger._internal(this.name); - void log(String msg) { if (!mute) print(msg); } diff --git a/examples/misc/lib/language_tour/classes/point.dart b/examples/misc/lib/language_tour/classes/point.dart index f3a69704c9..ea4bb3b718 100644 --- a/examples/misc/lib/language_tour/classes/point.dart +++ b/examples/misc/lib/language_tour/classes/point.dart @@ -8,11 +8,6 @@ const double yOrigin = 0; // #docregion class-with-distance-to, constructor-initializer class Point { - final double x; - final double y; - - // Sets the x and y instance variables - // before the constructor body runs. // #docregion class-with-distance-to, named-constructor Point(this.x, this.y); // #enddocregion class-with-distance-to, constructor-initializer @@ -24,6 +19,9 @@ class Point { y = yOrigin; // #enddocregion named-constructor + final double x; + final double y; + // Initializer list sets instance variables before // the constructor body runs. Point.fromJson(Map json) diff --git a/examples/misc/lib/language_tour/classes/point_redirecting.dart b/examples/misc/lib/language_tour/classes/point_redirecting.dart index 9fe2bc0272..c7c73c18ba 100644 --- a/examples/misc/lib/language_tour/classes/point_redirecting.dart +++ b/examples/misc/lib/language_tour/classes/point_redirecting.dart @@ -1,9 +1,9 @@ class Point { - double x, y; - // The main constructor for this class. Point(this.x, this.y); + double x, y; + // Delegates to the main constructor. Point.alongXAxis(double x) : this(x, 0); } diff --git a/examples/misc/lib/language_tour/classes/point_with_distance_field.dart b/examples/misc/lib/language_tour/classes/point_with_distance_field.dart index 233df0b699..728d399d22 100644 --- a/examples/misc/lib/language_tour/classes/point_with_distance_field.dart +++ b/examples/misc/lib/language_tour/classes/point_with_distance_field.dart @@ -2,14 +2,11 @@ import 'dart:math'; class Point { + Point(this.x, this.y) : distanceFromOrigin = sqrt(x * x + y * y); + final double x; final double y; final double distanceFromOrigin; - - Point(double x, double y) - : x = x, - y = y, - distanceFromOrigin = sqrt(x * x + y * y); } void main() { diff --git a/examples/misc/lib/language_tour/classes/super_initializer_parameters.dart b/examples/misc/lib/language_tour/classes/super_initializer_parameters.dart index 42c3c311e0..9a6f37d7da 100644 --- a/examples/misc/lib/language_tour/classes/super_initializer_parameters.dart +++ b/examples/misc/lib/language_tour/classes/super_initializer_parameters.dart @@ -5,10 +5,10 @@ class Vector2d { // #enddocregion named // #docregion positional + Vector2d(this.x, this.y); + final double x; final double y; - - Vector2d(this.x, this.y); // #enddocregion positional // #docregion named diff --git a/src/content/language/constructors.md b/src/content/language/constructors.md index b3ce8871d1..899432022f 100644 --- a/src/content/language/constructors.md +++ b/src/content/language/constructors.md @@ -14,7 +14,7 @@ nextpage: Declare a constructor by creating a function with the same name as its class (plus, optionally, an additional identifier as described in -[Named constructors](#named-constructors)). +[Named constructors](#named-constructors)). Use the most common constructor, the generative constructor, to create a new instance of a class, and [initializing formal parameters](#initializing-formal-parameters) @@ -23,18 +23,18 @@ to instantiate any instance variables, if necessary: ```dart class Point { - double x = 0; - double y = 0; - // Generative constructor with initializing formal parameters: Point(this.x, this.y); + + double x = 0; + double y = 0; } ``` The `this` keyword refers to the current instance. :::note -Use `this` only when there is a name conflict. +Use `this` only when there is a name conflict. Otherwise, Dart style omits the `this`. ::: @@ -42,9 +42,9 @@ Otherwise, Dart style omits the `this`. ## Initializing formal parameters Dart has *initializing formal parameters* to simplify the common pattern of -assigning a constructor argument to an instance variable. +assigning a constructor argument to an instance variable. Use `this.propertyName` directly in the constructor declaration, -and omit the body. +and omit the body. Initializing parameters also allow you to initialize non-nullable or `final` instance variables, @@ -53,12 +53,10 @@ which both must be initialized or provided a default value: ```dart class Point { + Point(this.x, this.y); + final double x; final double y; - - // Sets the x and y instance variables - // before the constructor body runs. - Point(this.x, this.y); } ``` @@ -67,25 +65,22 @@ are implicitly final and only in scope of the [initializer list](/language/constructors#initializer-list). If you need to perform some logic that cannot be expressed in the initializer list, -create a [factory constructor](#factory-constructors) +create a [factory constructor](#factory-constructors) (or [static method][]) with that logic and then pass the computed values to a normal constructor. - ## Default constructors If you don't declare a constructor, a default constructor is provided for you. The default constructor has no arguments and invokes the no-argument constructor in the superclass. - ## Constructors aren't inherited Subclasses don't inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, no name) constructor. - ## Named constructors Use a named constructor to implement multiple constructors for a class @@ -97,26 +92,23 @@ const double xOrigin = 0; const double yOrigin = 0; class Point { - final double x; - final double y; - - // Sets the x and y instance variables - // before the constructor body runs. Point(this.x, this.y); // Named constructor [!Point.origin()!] : x = xOrigin, y = yOrigin; + + final double x; + final double y; } ``` -Remember that constructors are not inherited, which means that a -superclass's named constructor is not inherited by a subclass. If you +Remember that constructors aren't inherited. This means that a +superclass's named constructor isn't inherited by a subclass. If you want a subclass to be created with a named constructor defined in the superclass, 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, @@ -141,11 +133,11 @@ constructor for its superclass, Person. Click **Run** to execute the code. ```dart:run-dartpad:height-450px:ga_id-non_default_superclass_constructor class Person { - String? firstName; - Person.fromJson(Map data) { print('in Person'); } + + String? firstName; } class Employee extends Person { @@ -166,7 +158,7 @@ void main() { } ``` -Because the arguments to the superclass constructor are evaluated before +As Dart evaluates the arguments to the superclass constructor before invoking the constructor, an argument can be an expression such as a function call: @@ -211,7 +203,7 @@ class Vector3d extends Vector2d { } ``` -Super-initializer parameters cannot be positional +Super-initializer parameters cannot be positional if the super-constructor invocation already has positional arguments, but they can always be named: @@ -234,7 +226,7 @@ class Vector3d extends Vector2d { ``` :::version-note -Using super-initializer parameters +Using super-initializer parameters requires a [language version][] of at least 2.17. If you're using an earlier language version, you must manually pass in all super constructor parameters. @@ -258,11 +250,10 @@ Point.fromJson(Map json) ``` :::warning -The right-hand side of an initializer doesn't have access to `this`. +The right-hand side of an initializer can't access `this`. ::: -During development, you can validate inputs by using `assert` in the -initializer list. +To validate inputs during development, add `assert` to the initializer list. ```dart @@ -271,23 +262,20 @@ Point.withAssert(this.x, this.y) : [!assert(x >= 0)!] { } ``` -Initializer lists are handy when setting up final fields. The following example -initializes three final fields in an initializer list. Click **Run** to execute -the code. +Initializer lists are handy when setting up final fields. +The following example initializes three final fields in an initializer list. +Click **Run** to execute the code. ```dart:run-dartpad:height-340px:ga_id-initializer_list import 'dart:math'; class Point { + Point(this.x, this.y) : distanceFromOrigin = sqrt(x * x + y * y); + final double x; final double y; final double distanceFromOrigin; - - Point(double x, double y) - : x = x, - y = y, - distanceFromOrigin = sqrt(x * x + y * y); } void main() { @@ -296,7 +284,6 @@ void main() { } ``` - ## Redirecting constructors Sometimes a constructor's only purpose is to redirect to another @@ -308,17 +295,16 @@ appearing after a colon (:). ```dart class Point { - double x, y; - // The main constructor for this class. Point(this.x, this.y); // Delegates to the main constructor. Point.alongXAxis(double x) : this(x, 0); + + double x, y; } ``` - ## Constant constructors If your class produces objects that never change, you can make these @@ -330,16 +316,14 @@ and make sure that all instance variables are `final`. class ImmutablePoint { static const ImmutablePoint origin = ImmutablePoint(0, 0); - final double x, y; - const ImmutablePoint(this.x, this.y); + + final double x, y; } ``` Constant constructors don't always create constants. -For details, see the section on -[using constructors][]. - +To learn more, consult the section on [using constructors][]. ## Factory constructors @@ -364,6 +348,8 @@ initializes a final variable from a JSON object. ```dart class Logger { + Logger._internal(this.name); + final String name; bool mute = false; @@ -379,8 +365,6 @@ class Logger { return Logger(json['name'].toString()); } - Logger._internal(this.name); - void log(String msg) { if (!mute) print(msg); } @@ -388,7 +372,7 @@ class Logger { ``` :::note -Factory constructors have no access to `this`. +Factory constructors can't access `this`. ::: Invoke a factory constructor just like you would any other constructor: From 415b0d7ea8788d1c44d4880a30bbfc2e309bb7fb Mon Sep 17 00:00:00 2001 From: Tony Sansone Date: Fri, 12 Apr 2024 13:23:15 -0500 Subject: [PATCH 2/3] Fixed excerpts --- src/content/language/constructors.md | 20 +++++++------------- src/content/language/methods.md | 5 ----- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/content/language/constructors.md b/src/content/language/constructors.md index 899432022f..de97639c27 100644 --- a/src/content/language/constructors.md +++ b/src/content/language/constructors.md @@ -23,11 +23,11 @@ to instantiate any instance variables, if necessary: ```dart class Point { - // Generative constructor with initializing formal parameters: - Point(this.x, this.y); - double x = 0; double y = 0; + + // Generative constructor with initializing formal parameters: + Point(this.x, this.y); } ``` @@ -54,9 +54,6 @@ which both must be initialized or provided a default value: ```dart class Point { Point(this.x, this.y); - - final double x; - final double y; } ``` @@ -98,9 +95,6 @@ class Point { [!Point.origin()!] : x = xOrigin, y = yOrigin; - - final double x; - final double y; } ``` @@ -188,10 +182,10 @@ Super-initializer parameters have similar syntax and semantics to ```dart class Vector2d { + Vector2d(this.x, this.y); + final double x; final double y; - - Vector2d(this.x, this.y); } class Vector3d extends Vector2d { @@ -298,10 +292,10 @@ class Point { // The main constructor for this class. Point(this.x, this.y); + double x, y; + // Delegates to the main constructor. Point.alongXAxis(double x) : this(x, 0); - - double x, y; } ``` diff --git a/src/content/language/methods.md b/src/content/language/methods.md index d855a5346e..a8f73125a6 100644 --- a/src/content/language/methods.md +++ b/src/content/language/methods.md @@ -24,11 +24,6 @@ instance method: import 'dart:math'; class Point { - final double x; - final double y; - - // Sets the x and y instance variables - // before the constructor body runs. Point(this.x, this.y); double distanceTo(Point other) { From 590c2b92416120cb69d30d1492b098ddec2793c8 Mon Sep 17 00:00:00 2001 From: Tony Sansone Date: Mon, 15 Apr 2024 14:49:59 -0500 Subject: [PATCH 3/3] Updated per @MaryaBelanger review --- examples/misc/lib/language_tour/classes/point.dart | 2 ++ examples/misc/lib/language_tour/classes/point_alt.dart | 6 +++--- src/content/language/constructors.md | 7 +++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/misc/lib/language_tour/classes/point.dart b/examples/misc/lib/language_tour/classes/point.dart index ea4bb3b718..7da355e57a 100644 --- a/examples/misc/lib/language_tour/classes/point.dart +++ b/examples/misc/lib/language_tour/classes/point.dart @@ -19,6 +19,8 @@ class Point { y = yOrigin; // #enddocregion named-constructor + // Sets the x and y instance variables + // before the constructor body runs. final double x; final double y; diff --git a/examples/misc/lib/language_tour/classes/point_alt.dart b/examples/misc/lib/language_tour/classes/point_alt.dart index 43f73dae5d..e697474bd9 100644 --- a/examples/misc/lib/language_tour/classes/point_alt.dart +++ b/examples/misc/lib/language_tour/classes/point_alt.dart @@ -6,11 +6,11 @@ /// // #docregion idiomatic-constructor class Point { - double x = 0; - double y = 0; - // Generative constructor with initializing formal parameters: Point(this.x, this.y); + + double x = 0; + double y = 0; // #enddocregion idiomatic-constructor // #docregion initializer-list diff --git a/src/content/language/constructors.md b/src/content/language/constructors.md index de97639c27..20291fd943 100644 --- a/src/content/language/constructors.md +++ b/src/content/language/constructors.md @@ -23,11 +23,11 @@ to instantiate any instance variables, if necessary: ```dart class Point { - double x = 0; - double y = 0; - // Generative constructor with initializing formal parameters: Point(this.x, this.y); + + double x = 0; + double y = 0; } ``` @@ -38,7 +38,6 @@ Use `this` only when there is a name conflict. Otherwise, Dart style omits the `this`. ::: - ## Initializing formal parameters Dart has *initializing formal parameters* to simplify the common pattern of