From 0a34e1a8d0b58c529df2f9d4969531000139a21f Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 11:17:54 -0800 Subject: [PATCH 01/80] adds examples for null safety codelab --- .../null_safety_codelab/analysis_options.yaml | 1 + .../bin/assertion_operator.dart | 14 ++++++++++++++ .../bin/conditional_access.dart | 14 ++++++++++++++ .../bin/definite_assignment.dart | 12 ++++++++++++ .../bin/late_circular_references.dart | 16 ++++++++++++++++ .../null_safety_codelab/bin/late_keyword.dart | 13 +++++++++++++ .../null_safety_codelab/bin/late_lazy.dart | 16 ++++++++++++++++ .../bin/more_nullable_types.dart | 9 +++++++++ .../bin/non_nullable_types.dart | 5 +++++ .../null_safety_codelab/bin/nullable_types.dart | 5 +++++ .../bin/promotion_exceptions.dart | 9 +++++++++ .../null_safety_codelab/bin/type_promotion.dart | 9 +++++++++ .../null_safety_codelab/pubspec.yaml | 10 ++++++++++ 13 files changed, 133 insertions(+) create mode 100644 null_safety_examples/null_safety_codelab/analysis_options.yaml create mode 100644 null_safety_examples/null_safety_codelab/bin/assertion_operator.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/conditional_access.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/definite_assignment.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/late_circular_references.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/late_keyword.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/late_lazy.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/nullable_types.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart create mode 100644 null_safety_examples/null_safety_codelab/bin/type_promotion.dart create mode 100644 null_safety_examples/null_safety_codelab/pubspec.yaml diff --git a/null_safety_examples/null_safety_codelab/analysis_options.yaml b/null_safety_examples/null_safety_codelab/analysis_options.yaml new file mode 100644 index 0000000000..5e2133eb69 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/analysis_options.yaml @@ -0,0 +1 @@ +include: ../analysis_options.yaml diff --git a/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart new file mode 100644 index 0000000000..9eebcd55a2 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart @@ -0,0 +1,14 @@ +int? couldReturnNullButDoesnt() => -3; + +void main() { + int? couldBeNullButIsnt = 1; + List listThatCouldHoldNulls = [2, null, 4]; + + int a = couldBeNullButIsnt; + int b = listThatCouldHoldNulls.first; + int c = couldReturnNullButDoesnt().abs(); + + print('a is $a.'); + print('b is $b.'); + print('c is $c.'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart new file mode 100644 index 0000000000..fe2861c481 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart @@ -0,0 +1,14 @@ +class BigThing { + LittleThing little = LittleThing(); +} + +class LittleThing { + int fetchInt() => 12; +} + +void main() { + final BigThing? big = BigThing(); + + print('The value is:'); + print(big.little.fetchInt()); +} diff --git a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart new file mode 100644 index 0000000000..bf283409b8 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart @@ -0,0 +1,12 @@ +void main() { + String text; + +// if (DateTime.now().hour < 12) { +// text = "It's morning! Let's make aloo paratha!"; +// } else { +// text = "It's afternoon! Let's make biryani!"; +// } + + print(text); + print(text.length); +} diff --git a/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart new file mode 100644 index 0000000000..1e2d4476ac --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart @@ -0,0 +1,16 @@ +class Team { + final Coach coach; +} + +class Coach { + final Team team; +} + +void main() { + final myTeam = Team(); + final myCoach = Coach(); + myTeam.coach = myCoach; + myCoach.team = myTeam; + + print ('All done!'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/late_keyword.dart b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart new file mode 100644 index 0000000000..dcf14ecb6a --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart @@ -0,0 +1,13 @@ +class Meal { + String description; + + void setDescription(String str) { + description = str; + } +} + +void main() { + final myMeal = Meal(); + myMeal.setDescription('Feijoada!'); + print(myMeal.description); +} diff --git a/null_safety_examples/null_safety_codelab/bin/late_lazy.dart b/null_safety_examples/null_safety_codelab/bin/late_lazy.dart new file mode 100644 index 0000000000..016e07914e --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/late_lazy.dart @@ -0,0 +1,16 @@ +int _computeValue() { + print('Computing value...'); + return 3; +} + +class CachedValueProvider { + final _cache = _computeValue(); + int get value => _cache; +} + +void main() { + print('Calling constructor...'); + var provider = CachedValueProvider(); + print('Getting value...'); + print('The value is ${provider.value}!'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart new file mode 100644 index 0000000000..374ac89024 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart @@ -0,0 +1,9 @@ +void main() { + List aListofStrings = ['one', 'two', 'three']; + List aNullableListOfStrings; + List aListofNullableStrings = ['one', null, 'three']; + + print('aListofStrings is $aListofStrings.'); + print('aNullableListOfStrings is $aNullableListOfStrings.'); + print('aListofNullableStrings is $aListofNullableStrings.'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart new file mode 100644 index 0000000000..ee20e646d5 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart @@ -0,0 +1,5 @@ +void main() { + int a; + a = null; + print('a is $a.'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/nullable_types.dart new file mode 100644 index 0000000000..ee20e646d5 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/nullable_types.dart @@ -0,0 +1,5 @@ +void main() { + int a; + a = null; + print('a is $a.'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart new file mode 100644 index 0000000000..774f3f6915 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart @@ -0,0 +1,9 @@ +int getLength(String? str) { + // Try throwing here if `str` is null. + + return str.length; +} + +void main() { + print(getLength(null)); +} diff --git a/null_safety_examples/null_safety_codelab/bin/type_promotion.dart b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart new file mode 100644 index 0000000000..7dcc59b41a --- /dev/null +++ b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart @@ -0,0 +1,9 @@ +int getLength(String? str) { + // Add null check here + + return str.length; +} + +void main() { + print(getLength('This is a string!')); +} diff --git a/null_safety_examples/null_safety_codelab/pubspec.yaml b/null_safety_examples/null_safety_codelab/pubspec.yaml new file mode 100644 index 0000000000..628837d4e9 --- /dev/null +++ b/null_safety_examples/null_safety_codelab/pubspec.yaml @@ -0,0 +1,10 @@ +name: null_safety_codelab +description: dart.dev example code for null safety codelab + +environment: + sdk: ">=2.12.0-0 <3.0.0" + +dev_dependencies: + examples_util: {path: ../util} + pedantic: ^1.10.0-nullsafety.3 + test: ^1.16.0-nullsafety.13 From 05f16d5d833fdfb1a59af6944467f782d951327d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 12:16:04 -0800 Subject: [PATCH 02/80] adds null safety codelab and updates side-nav --- src/_data/side-nav.yml | 2 + src/codelabs/null-safety.md | 358 ++++++++++++++++++++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 src/codelabs/null-safety.md diff --git a/src/_data/side-nav.yml b/src/_data/side-nav.yml index e4d8d03afa..7e53d5a81f 100644 --- a/src/_data/side-nav.yml +++ b/src/_data/side-nav.yml @@ -16,6 +16,8 @@ permalink: /codelabs/iterables - title: Asynchronous programming permalink: /codelabs/async-await + - title: Null safety + permalink: /codelabs/null-safety - title: Tutorials urlExactMatch: true match-page-url-exactly: true diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md new file mode 100644 index 0000000000..cc99f2d6dd --- /dev/null +++ b/src/codelabs/null-safety.md @@ -0,0 +1,358 @@ +--- +title: "Null safety" +description: Learn about and practice writing null safe code in DartPad! +js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] +--- +{% assign useIframe = false -%} + + + + +This codelab teaches you about Dart’s null safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be null unless you say they can be. + +Using embedded DartPad editors, you can test your knowledge by running example code and completing exercises. To get the most out of this codelab, you should have some knowledge of [basic Dart syntax](/samples). + +This codelab covers the following material: + +* Nullable and non-nullable types. +* How and when to use the null-aware operators: ? and ! +* How the late keyword affects variables and initialization. + +{{site.alert.note}} + This page uses embedded DartPads to display examples and exercises. + {% include dartpads-embedded-troubleshooting.md %} +{{site.alert.end}} + + +# What is null safety? + +Dart's null safe type system makes types in your code non-nullable by default, +meaning that values can't be null unless you say they can be. Null safety helps +prevent null reference errors. + +Here are some core principles +of sound null safety in the Dart language: + +- All types are non-nullable by default. +- Values can't be null unless you say they can be. +- Finding null errors at edit time is much better than finding them at run + time. + +## Non-nullable types + +All types are non-nullable by default. For example, if you have a variable of +type String, it will always contain a string. + +## Nullable types + +If you want a variable of type String to accept any string, or the value null +but nothing else, you give the variable a nullable type by adding a `?` after +the type name. For example, a variable of type String? can contain a string, or +it can be null. + +## Example: Introducing non-nullable types + +The variable `a` below is declared as an `int`. Try changing the value in the +assignment to 3 or 145. Anything but null! + + +```dart +void main() { + int a; + a = null; + print('a is $a.'); +} +``` + +## Example: Nullable types + +What if you need a variable that *can* hold a null value? Try changing the +type of `a` so that `a` can be either null or an int: + + +```dart +void main() { + int a; + a = null; + print('a is $a.'); +} +``` + +## Example: More nullable types! + +Type parameters for generics can also be nullable or non-nullable. Try using +question marks to correct the type declarations of `aNullableListOfStrings` and +`aListOfNullableStrings`: + + +```dart +void main() { + List aListofStrings = ['one', 'two', 'three']; + List aNullableListOfStrings; + List aListofNullableStrings = ['one', null, 'three']; + + print('aListofStrings is $aListofStrings.'); + print('aNullableListOfStrings is $aNullableListOfStrings.'); + print('aListofNullableStrings is $aListofNullableStrings.'); +} +``` + +## Example: Definite assignment + +Dart's type system is crafty enough to track where variables are assigned and +where their values are read, and to verify that non-nullable fields are given +values before any code tries to read from them. This process is called "definite +assignment." + +Try uncommenting the if-else statement in the code below, and watch the +analyzer errors disappear: + + +```dart +void main() { + String text; + +// if (DateTime.now().hour < 12) { +// text = "It's morning! Let's make aloo paratha!"; +// } else { +// text = "It's afternoon! Let's make biryani!"; +// } + + print(text); + print(text.length); +} +``` + +# New null-aware operators: ? and ! + +Null safety introduces two operators, ? and !. Here's how you use them: + +- If you're creating a variable that can have the value null, add a + question mark (?) to the variable's type declaration. Types are + non-nullable by default and made nullable by adding ?. +- If you're accessing a property and the operand might be null, use the + null-aware version member access operator (?.). +- If you're sure that an expression with a nullable type isn't null, you + can add a postfix exclamation mark (!) to make Dart treat it as non-nullable. + +## Example: Conditional access + +Conditional access is a handy way to tighten up code that needs to read +properties that could be null. For example, the following expression evaluates +to the value of `b` as long as `a` isn't null. If `a` is null, then the +expression evaluates to null: + + a?.b + +Without null safety, *two* conditional access operators are needed for the +following code to work: one after `big` and one after `little`. With null +safety, conditional access can short-circuit, so this expression only requires a +single `?`: + + +```dart +class BigThing { + LittleThing little = LittleThing(); +} + +class LittleThing { + int fetchInt() => 12; +} + +void main() { + final BigThing? big = BigThing(); + + print('The value is:'); + print(big.little.fetchInt()); +} +``` + +## Example: The assertion operator `!` + +If you'd like to assign a nullable expression to a variable that's +non-nullable, you can use the assertion operator (the exclamation point: `!`). +By adding `!` just after the expression, you tell Dart that the value won't be +null, and that it's safe to assign it to a non-nullable variable. If you're +wrong, Dart throws an exception. + +In the example below, try adding exclamation points to correct the\ +three broken assignments: + + +```dart +int? couldReturnNullButDoesnt() => -3; + +void main() { + int? couldBeNullButIsnt = 1; + List listThatCouldHoldNulls = [2, null, 4]; + + int a = couldBeNullButIsnt; + int b = listThatCouldHoldNulls.first; + int c = couldReturnNullButDoesnt().abs(); + + print('a is $a.'); + print('b is $b.'); + print('c is $c.'); +} +``` + +## Exercise: Type promotion + +With null safety, Dart takes null checks into account. Nullable variables that +can't possibly contain null are treated like non-nullable variables. This +behavior is called "promotion." + +In the example below, add an if statement to the beginning of `getLength` that +returns zero if `str` is null: + + +```dart +int getLength(String? str) { + // Add null check here + + return str.length; +} + +void main() { + print(getLength('This is a string!')); +} +``` + +## Exercise: Promotion with exceptions + +Promotion works with exceptions as well as return statements. Try a null check +that throws an `Exception` instead of returning zero. + + +```dart +int getLength(String? str) { + // Try throwing here if `str` is null. + + return str.length; +} + +void main() { + print(getLength(null)); +} +``` + +# Late keyword + +Sometimes fields in a class *should* be non-nullable, but those fields can't be +assigned a value immediately. For cases like that, use the `late` keyword. +`late` is how you tell Dart that: + +- You aren't going to assign that field a value right away. +- But you *are* going to assign it a value later. +- And you'll make sure it's assigned a value *before* it's accessed. + +If you declare a field `late` and the field is read before it is assigned a +value, a `LateInitializationError` is thrown to tell you what went wrong. + +## Example: The `late` keyword + +Try using the `late` keyword to correct the following code. For a little extra +fun afterward, try commenting out the line that sets `description`! + + +```dart +class Meal { + String description; + + void setDescription(String str) { + description = str; + } +} + +void main() { + final myMeal = Meal(); + myMeal.setDescription('Feijoada!'); + print(myMeal.description); +} +``` + +## Example: Late circular references + +The `late` keyword is really helpful for tricky patterns like circular +references. Here are two objects that need to maintain non-nullable references +to each other. Try using the `late` keyword to fix this code. Note that you +don't have to remove `final`. `late` fields can also be `final`: you set `late +final` values once, and after that they're read-only. + + +```dart +class Team { + final Coach coach; +} + +class Coach { + final Team team; +} + +void main() { + final myTeam = Team(); + final myCoach = Coach(); + myTeam.coach = myCoach; + myCoach.team = myTeam; + + print ('All done!'); +} +``` + +## Example: Late and lazy + +Here's another pattern that `late` can help with: lazy initialization for +expensive non-nullable fields. Try running this code without changing it. What +do you think will change if you make `_cache` a `late` field? + + +```dart +int _computeValue() { + print('Computing value...'); + return 3; +} + +class CachedValueProvider { + final _cache = _computeValue(); + int get value => _cache; +} + +void main() { + print('Calling constructor...'); + var provider = CachedValueProvider(); + print('Getting value...'); + print('The value is ${provider.value}!'); +} +``` + +Fun fact: After you add `late` to the declaration of `_cache`, you can move the +`_computeValue` function into the `CachedValueProvider` class and the code will +still work! Initialization expressions for `late` fields can use instance +methods in their initializers. + +# What's next? + +Congratulations, you've finished the codelab! If you'd like to learn more, here +are some suggestions for where to go next: + +- [Play with DartPad](https://nullsafety.dartpad.dev/). +- Try another [codelab](https://dart.dev/codelabs). +- Learn more about null safety: + - Overview: [Sound null safety](https://dart.dev/null-safety) + - Deep dive: + [Understanding null safety](https://dart.dev/null-safety/understanding-null-safet). +- [Get the Dart SDK](https://dart.dev/get-dart). + +If you're interested in using embedded DartPads, like this codelab does, see +[best practices for using DartPad in tutorials](https://dart.dev/resources/dartpad-best-practices). \ No newline at end of file From e11c8faf7d8bb910223ae15a95e8786de7aa9398 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 12:57:03 -0800 Subject: [PATCH 03/80] Update null-safety.md fixes headings --- src/codelabs/null-safety.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index cc99f2d6dd..eefc7731a5 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -35,7 +35,7 @@ This codelab covers the following material: {{site.alert.end}} -# What is null safety? +## What is null safety? Dart's null safe type system makes types in your code non-nullable by default, meaning that values can't be null unless you say they can be. Null safety helps @@ -61,7 +61,7 @@ but nothing else, you give the variable a nullable type by adding a `?` after the type name. For example, a variable of type String? can contain a string, or it can be null. -## Example: Introducing non-nullable types +### Example: Introducing non-nullable types The variable `a` below is declared as an `int`. Try changing the value in the assignment to 3 or 145. Anything but null! @@ -75,7 +75,7 @@ void main() { } ``` -## Example: Nullable types +### Example: Nullable types What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: @@ -89,7 +89,7 @@ void main() { } ``` -## Example: More nullable types! +### Example: More nullable types! Type parameters for generics can also be nullable or non-nullable. Try using question marks to correct the type declarations of `aNullableListOfStrings` and @@ -108,7 +108,7 @@ void main() { } ``` -## Example: Definite assignment +### Example: Definite assignment Dart's type system is crafty enough to track where variables are assigned and where their values are read, and to verify that non-nullable fields are given @@ -134,7 +134,7 @@ void main() { } ``` -# New null-aware operators: ? and ! +## New null-aware operators: ? and ! Null safety introduces two operators, ? and !. Here's how you use them: @@ -146,7 +146,7 @@ Null safety introduces two operators, ? and !. Here's how you use them: - If you're sure that an expression with a nullable type isn't null, you can add a postfix exclamation mark (!) to make Dart treat it as non-nullable. -## Example: Conditional access +### Example: Conditional access Conditional access is a handy way to tighten up code that needs to read properties that could be null. For example, the following expression evaluates @@ -178,7 +178,7 @@ void main() { } ``` -## Example: The assertion operator `!` +### Example: The assertion operator `!` If you'd like to assign a nullable expression to a variable that's non-nullable, you can use the assertion operator (the exclamation point: `!`). @@ -207,7 +207,7 @@ void main() { } ``` -## Exercise: Type promotion +### Exercise: Type promotion With null safety, Dart takes null checks into account. Nullable variables that can't possibly contain null are treated like non-nullable variables. This @@ -229,7 +229,7 @@ void main() { } ``` -## Exercise: Promotion with exceptions +### Exercise: Promotion with exceptions Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. @@ -247,7 +247,7 @@ void main() { } ``` -# Late keyword +## Late keyword Sometimes fields in a class *should* be non-nullable, but those fields can't be assigned a value immediately. For cases like that, use the `late` keyword. @@ -260,7 +260,7 @@ assigned a value immediately. For cases like that, use the `late` keyword. If you declare a field `late` and the field is read before it is assigned a value, a `LateInitializationError` is thrown to tell you what went wrong. -## Example: The `late` keyword +### Example: The `late` keyword Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! @@ -282,7 +282,7 @@ void main() { } ``` -## Example: Late circular references +### Example: Late circular references The `late` keyword is really helpful for tricky patterns like circular references. Here are two objects that need to maintain non-nullable references @@ -310,7 +310,7 @@ void main() { } ``` -## Example: Late and lazy +### Example: Late and lazy Here's another pattern that `late` can help with: lazy initialization for expensive non-nullable fields. Try running this code without changing it. What @@ -341,7 +341,7 @@ Fun fact: After you add `late` to the declaration of `_cache`, you can move the still work! Initialization expressions for `late` fields can use instance methods in their initializers. -# What's next? +## What's next? Congratulations, you've finished the codelab! If you'd like to learn more, here are some suggestions for where to go next: @@ -355,4 +355,4 @@ are some suggestions for where to go next: - [Get the Dart SDK](https://dart.dev/get-dart). If you're interested in using embedded DartPads, like this codelab does, see -[best practices for using DartPad in tutorials](https://dart.dev/resources/dartpad-best-practices). \ No newline at end of file +[best practices for using DartPad in tutorials](https://dart.dev/resources/dartpad-best-practices). From 84940e47f1ac9c37714b50c7a49586d5201b1793 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 13:51:57 -0800 Subject: [PATCH 04/80] adds regex for first example --- .../bin/non_nullable_types.dart | 2 +- src/codelabs/null-safety.md | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart index ee20e646d5..212386d29a 100644 --- a/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart +++ b/null_safety_examples/null_safety_codelab/bin/non_nullable_types.dart @@ -1,5 +1,5 @@ void main() { int a; - a = null; + a = 145; print('a is $a.'); } diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index eefc7731a5..e7d371320a 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -66,11 +66,11 @@ it can be null. The variable `a` below is declared as an `int`. Try changing the value in the assignment to 3 or 145. Anything but null! - + ```dart void main() { int a; - a = null; + a = 145; print('a is $a.'); } ``` @@ -80,7 +80,7 @@ void main() { What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: - + ```dart void main() { int a; @@ -95,7 +95,7 @@ Type parameters for generics can also be nullable or non-nullable. Try using question marks to correct the type declarations of `aNullableListOfStrings` and `aListOfNullableStrings`: - + ```dart void main() { List aListofStrings = ['one', 'two', 'three']; @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; @@ -160,7 +160,7 @@ following code to work: one after `big` and one after `little`. With null safety, conditional access can short-circuit, so this expression only requires a single `?`: - + ```dart class BigThing { LittleThing little = LittleThing(); @@ -189,7 +189,7 @@ wrong, Dart throws an exception. In the example below, try adding exclamation points to correct the\ three broken assignments: - + ```dart int? couldReturnNullButDoesnt() => -3; @@ -216,7 +216,7 @@ behavior is called "promotion." In the example below, add an if statement to the beginning of `getLength` that returns zero if `str` is null: - + ```dart int getLength(String? str) { // Add null check here @@ -234,7 +234,7 @@ void main() { Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. - + ```dart int getLength(String? str) { // Try throwing here if `str` is null. @@ -265,7 +265,7 @@ value, a `LateInitializationError` is thrown to tell you what went wrong. Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! - + ```dart class Meal { String description; @@ -290,7 +290,7 @@ to each other. Try using the `late` keyword to fix this code. Note that you don't have to remove `final`. `late` fields can also be `final`: you set `late final` values once, and after that they're read-only. - + ```dart class Team { final Coach coach; @@ -316,7 +316,7 @@ Here's another pattern that `late` can help with: lazy initialization for expensive non-nullable fields. Try running this code without changing it. What do you think will change if you make `_cache` a `late` field? - + ```dart int _computeValue() { print('Computing value...'); From ea6f717fa52344fcfb1591fd9d152c9542f4efce Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 14:49:06 -0800 Subject: [PATCH 05/80] adds regex for more_nullable_types and nullable_types examples --- .../bin/more_nullable_types.dart | 8 +++---- .../bin/nullable_types.dart | 2 +- src/codelabs/null-safety.md | 22 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart index 374ac89024..f970023ad1 100644 --- a/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart +++ b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart @@ -1,9 +1,9 @@ void main() { List aListofStrings = ['one', 'two', 'three']; - List aNullableListOfStrings; - List aListofNullableStrings = ['one', null, 'three']; - + List aNullableListOfStrings = []; + List aListofNullableStrings = ['one', null, 'three']; + print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); print('aListofNullableStrings is $aListofNullableStrings.'); -} +} \ No newline at end of file diff --git a/null_safety_examples/null_safety_codelab/bin/nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/nullable_types.dart index ee20e646d5..d5ec78d3b1 100644 --- a/null_safety_examples/null_safety_codelab/bin/nullable_types.dart +++ b/null_safety_examples/null_safety_codelab/bin/nullable_types.dart @@ -1,5 +1,5 @@ void main() { - int a; + int? a; a = null; print('a is $a.'); } diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index e7d371320a..8f7fcb6c5d 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -80,10 +80,10 @@ void main() { What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: - + ```dart void main() { - int a; + int? a; a = null; print('a is $a.'); } @@ -95,12 +95,12 @@ Type parameters for generics can also be nullable or non-nullable. Try using question marks to correct the type declarations of `aNullableListOfStrings` and `aListOfNullableStrings`: - + ```dart void main() { List aListofStrings = ['one', 'two', 'three']; - List aNullableListOfStrings; - List aListofNullableStrings = ['one', null, 'three']; + List aNullableListOfStrings = []; + List aListofNullableStrings = ['one', null, 'three']; print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); @@ -122,12 +122,12 @@ analyzer errors disappear: ```dart void main() { String text; - -// if (DateTime.now().hour < 12) { -// text = "It's morning! Let's make aloo paratha!"; -// } else { -// text = "It's afternoon! Let's make biryani!"; -// } + + if (DateTime.now().hour < 12) { + text = "It's morning! Let's make aloo paratha!"; + } else { + text = "It's afternoon! Let's make biryani!"; + } print(text); print(text.length); From f0c18f2346e5ad687c6a66ab451e0b4b431ec04c Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 14:54:22 -0800 Subject: [PATCH 06/80] fixes some typos --- src/codelabs/null-safety.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 8f7fcb6c5d..4a27a8a190 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; @@ -160,7 +160,7 @@ following code to work: one after `big` and one after `little`. With null safety, conditional access can short-circuit, so this expression only requires a single `?`: - + ```dart class BigThing { LittleThing little = LittleThing(); @@ -189,7 +189,7 @@ wrong, Dart throws an exception. In the example below, try adding exclamation points to correct the\ three broken assignments: - + ```dart int? couldReturnNullButDoesnt() => -3; @@ -216,7 +216,7 @@ behavior is called "promotion." In the example below, add an if statement to the beginning of `getLength` that returns zero if `str` is null: - + ```dart int getLength(String? str) { // Add null check here @@ -234,7 +234,7 @@ void main() { Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. - + ```dart int getLength(String? str) { // Try throwing here if `str` is null. @@ -265,7 +265,7 @@ value, a `LateInitializationError` is thrown to tell you what went wrong. Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! - + ```dart class Meal { String description; @@ -290,7 +290,7 @@ to each other. Try using the `late` keyword to fix this code. Note that you don't have to remove `final`. `late` fields can also be `final`: you set `late final` values once, and after that they're read-only. - + ```dart class Team { final Coach coach; @@ -316,7 +316,7 @@ Here's another pattern that `late` can help with: lazy initialization for expensive non-nullable fields. Try running this code without changing it. What do you think will change if you make `_cache` a `late` field? - + ```dart int _computeValue() { print('Computing value...'); @@ -351,7 +351,7 @@ are some suggestions for where to go next: - Learn more about null safety: - Overview: [Sound null safety](https://dart.dev/null-safety) - Deep dive: - [Understanding null safety](https://dart.dev/null-safety/understanding-null-safet). + [Understanding null safety](https://dart.dev/null-safety/understanding-null-safety). - [Get the Dart SDK](https://dart.dev/get-dart). If you're interested in using embedded DartPads, like this codelab does, see From 44655b6e385e7016635dee9d81826b386589948d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 15:07:22 -0800 Subject: [PATCH 07/80] fixes a typo --- src/codelabs/null-safety.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 4a27a8a190..6de8f11fc3 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -70,7 +70,7 @@ assignment to 3 or 145. Anything but null! ```dart void main() { int a; - a = 145; + a = null; print('a is $a.'); } ``` @@ -83,7 +83,7 @@ type of `a` so that `a` can be either null or an int: ```dart void main() { - int? a; + int a; a = null; print('a is $a.'); } @@ -99,8 +99,8 @@ question marks to correct the type declarations of `aNullableListOfStrings` and ```dart void main() { List aListofStrings = ['one', 'two', 'three']; - List aNullableListOfStrings = []; - List aListofNullableStrings = ['one', null, 'three']; + List aNullableListOfStrings = []; + List aListofNullableStrings = ['one', null, 'three']; print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); @@ -122,12 +122,12 @@ analyzer errors disappear: ```dart void main() { String text; - - if (DateTime.now().hour < 12) { - text = "It's morning! Let's make aloo paratha!"; - } else { - text = "It's afternoon! Let's make biryani!"; - } + +// if (DateTime.now().hour < 12) { +// text = "It's morning! Let's make aloo paratha!"; +// } else { +// text = "It's afternoon! Let's make biryani!"; +// } print(text); print(text.length); @@ -221,7 +221,7 @@ returns zero if `str` is null: int getLength(String? str) { // Add null check here - return str.length; + return str.length; } void main() { @@ -239,7 +239,7 @@ that throws an `Exception` instead of returning zero. int getLength(String? str) { // Try throwing here if `str` is null. - return str.length; + return str.length; } void main() { @@ -290,7 +290,7 @@ to each other. Try using the `late` keyword to fix this code. Note that you don't have to remove `final`. `late` fields can also be `final`: you set `late final` values once, and after that they're read-only. - + ```dart class Team { final Coach coach; From 04f185bd485a0cba9b40d064f8d421ffc379361c Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 15:11:02 -0800 Subject: [PATCH 08/80] . --- src/codelabs/null-safety.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 6de8f11fc3..47b74628a2 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -70,7 +70,7 @@ assignment to 3 or 145. Anything but null! ```dart void main() { int a; - a = null; + a = 145; print('a is $a.'); } ``` @@ -83,7 +83,7 @@ type of `a` so that `a` can be either null or an int: ```dart void main() { - int a; + int? a; a = null; print('a is $a.'); } @@ -99,8 +99,8 @@ question marks to correct the type declarations of `aNullableListOfStrings` and ```dart void main() { List aListofStrings = ['one', 'two', 'three']; - List aNullableListOfStrings = []; - List aListofNullableStrings = ['one', null, 'three']; + List aNullableListOfStrings = []; + List aListofNullableStrings = ['one', null, 'three']; print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); From 358b6467bfa31db03931912bb7a8597eaf1246dc Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 15:17:13 -0800 Subject: [PATCH 09/80] ran refresher script --- src/codelabs/null-safety.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 47b74628a2..6de8f11fc3 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -70,7 +70,7 @@ assignment to 3 or 145. Anything but null! ```dart void main() { int a; - a = 145; + a = null; print('a is $a.'); } ``` @@ -83,7 +83,7 @@ type of `a` so that `a` can be either null or an int: ```dart void main() { - int? a; + int a; a = null; print('a is $a.'); } @@ -99,8 +99,8 @@ question marks to correct the type declarations of `aNullableListOfStrings` and ```dart void main() { List aListofStrings = ['one', 'two', 'three']; - List aNullableListOfStrings = []; - List aListofNullableStrings = ['one', null, 'three']; + List aNullableListOfStrings = []; + List aListofNullableStrings = ['one', null, 'three']; print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); From 407f8a0390ab1e04a1454fc4d7062f0ac03c585a Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 15:44:38 -0800 Subject: [PATCH 10/80] adds regex for definite_assignment --- .../null_safety_codelab/bin/definite_assignment.dart | 10 +++++----- src/codelabs/null-safety.md | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart index bf283409b8..4af0d2ecdb 100644 --- a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart +++ b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart @@ -1,11 +1,11 @@ void main() { String text; -// if (DateTime.now().hour < 12) { -// text = "It's morning! Let's make aloo paratha!"; -// } else { -// text = "It's afternoon! Let's make biryani!"; -// } + if (DateTime.now().hour < 12) { + text = "It's morning! Let's make aloo paratha!"; + } else { + text = "It's afternoon! Let's make biryani!"; + } print(text); print(text.length); diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 6de8f11fc3..be63854606 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,16 +118,16 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; -// if (DateTime.now().hour < 12) { -// text = "It's morning! Let's make aloo paratha!"; -// } else { -// text = "It's afternoon! Let's make biryani!"; -// } + if (DateTime.now().hour < 12) { + text = "It's morning! Let's make aloo paratha!"; + } else { + text = "It's afternoon! Let's make biryani!"; + } print(text); print(text.length); From e3ae99683e9ca161dfad6b0b33fd42061ba044a8 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 15:51:33 -0800 Subject: [PATCH 11/80] fixes a typo in part of the definite_assignment regex --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index be63854606..89a3fcdbae 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From 2ee2068696d3b1fa00edd393ec66f1d323d07beb Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 16:18:47 -0800 Subject: [PATCH 12/80] . --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 89a3fcdbae..992b2503b0 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From e521724bd5c8c0ba3e28ea51e02ebcf20db46598 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 16:27:08 -0800 Subject: [PATCH 13/80] . --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 992b2503b0..f7bd719f20 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From c9f37be7b7c5bf12f275742136dc412fd2195104 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 16:29:45 -0800 Subject: [PATCH 14/80] . --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index f7bd719f20..1e4705debe 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From 00c10286e99494f0f3a2f42a39b5731d02f774d0 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 16:58:09 -0800 Subject: [PATCH 15/80] fixes a typo!!!! --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 1e4705debe..79dbaf6c49 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From 790110c4273fccce49028f4e5285b5865acfc377 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 17:37:39 -0800 Subject: [PATCH 16/80] finished regex for definite_assignment --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 79dbaf6c49..be606d7fc7 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -118,7 +118,7 @@ assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: - + ```dart void main() { String text; From a23209b2aa85e2e9495b925f9c481ac754728d4d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 18:28:59 -0800 Subject: [PATCH 17/80] adds remaining regexes --- .../bin/assertion_operator.dart | 4 +-- .../bin/conditional_access.dart | 2 +- .../bin/late_circular_references.dart | 6 ++--- .../null_safety_codelab/bin/late_keyword.dart | 4 +-- src/codelabs/null-safety.md | 27 +++++++++---------- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart index 9eebcd55a2..d39e600a96 100644 --- a/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart +++ b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart @@ -5,8 +5,8 @@ void main() { List listThatCouldHoldNulls = [2, null, 4]; int a = couldBeNullButIsnt; - int b = listThatCouldHoldNulls.first; - int c = couldReturnNullButDoesnt().abs(); + int b = listThatCouldHoldNulls.first!; // first item in the list + int c = couldReturnNullButDoesnt()!.abs(); // absolute value print('a is $a.'); print('b is $b.'); diff --git a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart index fe2861c481..2a72ec0cd7 100644 --- a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart +++ b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart @@ -10,5 +10,5 @@ void main() { final BigThing? big = BigThing(); print('The value is:'); - print(big.little.fetchInt()); + print(big?.little.fetchInt()); } diff --git a/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart index 1e2d4476ac..146d6ca3dd 100644 --- a/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart +++ b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart @@ -1,9 +1,9 @@ class Team { - final Coach coach; + late final Coach coach; } class Coach { - final Team team; + late final Team team; } void main() { @@ -13,4 +13,4 @@ void main() { myCoach.team = myTeam; print ('All done!'); -} +} \ No newline at end of file diff --git a/null_safety_examples/null_safety_codelab/bin/late_keyword.dart b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart index dcf14ecb6a..42879bf56e 100644 --- a/null_safety_examples/null_safety_codelab/bin/late_keyword.dart +++ b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart @@ -1,5 +1,5 @@ class Meal { - String description; + late String description; void setDescription(String str) { description = str; @@ -10,4 +10,4 @@ void main() { final myMeal = Meal(); myMeal.setDescription('Feijoada!'); print(myMeal.description); -} +} \ No newline at end of file diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index be606d7fc7..14e7b2a4bf 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -123,11 +123,11 @@ analyzer errors disappear: void main() { String text; - if (DateTime.now().hour < 12) { - text = "It's morning! Let's make aloo paratha!"; - } else { - text = "It's afternoon! Let's make biryani!"; - } + //if (DateTime.now().hour < 12) { + // text = "It's morning! Let's make aloo paratha!"; + //} else { + // text = "It's afternoon! Let's make biryani!"; + //} print(text); print(text.length); @@ -160,7 +160,7 @@ following code to work: one after `big` and one after `little`. With null safety, conditional access can short-circuit, so this expression only requires a single `?`: - + ```dart class BigThing { LittleThing little = LittleThing(); @@ -186,10 +186,9 @@ By adding `!` just after the expression, you tell Dart that the value won't be null, and that it's safe to assign it to a non-nullable variable. If you're wrong, Dart throws an exception. -In the example below, try adding exclamation points to correct the\ -three broken assignments: +In the example below, try adding exclamation points to correct the three broken assignments: - + ```dart int? couldReturnNullButDoesnt() => -3; @@ -198,8 +197,8 @@ void main() { List listThatCouldHoldNulls = [2, null, 4]; int a = couldBeNullButIsnt; - int b = listThatCouldHoldNulls.first; - int c = couldReturnNullButDoesnt().abs(); + int b = listThatCouldHoldNulls.first; // first item in the list + int c = couldReturnNullButDoesnt().abs(); // absolute value print('a is $a.'); print('b is $b.'); @@ -265,7 +264,7 @@ value, a `LateInitializationError` is thrown to tell you what went wrong. Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! - + ```dart class Meal { String description; @@ -290,7 +289,7 @@ to each other. Try using the `late` keyword to fix this code. Note that you don't have to remove `final`. `late` fields can also be `final`: you set `late final` values once, and after that they're read-only. - + ```dart class Team { final Coach coach; @@ -310,7 +309,7 @@ void main() { } ``` -### Example: Late and lazy +### Exercise: Late and lazy Here's another pattern that `late` can help with: lazy initialization for expensive non-nullable fields. Try running this code without changing it. What From 404fb004da65ae0baa51349610626e5555ada70d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:31:14 -0800 Subject: [PATCH 18/80] more changes to regexes --- .../bin/definite_assignment.dart | 10 +++++----- .../bin/promotion_exceptions.dart | 6 ++++-- .../null_safety_codelab/bin/type_promotion.dart | 4 +++- src/codelabs/null-safety.md | 16 ++++++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart index 4af0d2ecdb..366d7f28d3 100644 --- a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart +++ b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart @@ -1,11 +1,11 @@ void main() { String text; - if (DateTime.now().hour < 12) { - text = "It's morning! Let's make aloo paratha!"; - } else { - text = "It's afternoon! Let's make biryani!"; - } + if (DateTime.now().hour < 12) { + text = "It's morning! Let's make aloo paratha!"; + } else { + text = "It's afternoon! Let's make biryani!"; + } print(text); print(text.length); diff --git a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart index 774f3f6915..4356521b6a 100644 --- a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart +++ b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart @@ -1,6 +1,8 @@ int getLength(String? str) { - // Try throwing here if `str` is null. - + // Try throwing exception here if `str` is null. + if (str == null) { + return Exception("String is null"); + } return str.length; } diff --git a/null_safety_examples/null_safety_codelab/bin/type_promotion.dart b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart index 7dcc59b41a..9b3bfe9f5c 100644 --- a/null_safety_examples/null_safety_codelab/bin/type_promotion.dart +++ b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart @@ -1,6 +1,8 @@ int getLength(String? str) { // Add null check here - + if (str == null) { + return 0; + } return str.length; } diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 14e7b2a4bf..a363bcf705 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -123,11 +123,11 @@ analyzer errors disappear: void main() { String text; - //if (DateTime.now().hour < 12) { - // text = "It's morning! Let's make aloo paratha!"; - //} else { - // text = "It's afternoon! Let's make biryani!"; - //} + //if (DateTime.now().hour < 12) { + // text = "It's morning! Let's make aloo paratha!"; + //} else { + // text = "It's afternoon! Let's make biryani!"; + //} print(text); print(text.length); @@ -215,7 +215,7 @@ behavior is called "promotion." In the example below, add an if statement to the beginning of `getLength` that returns zero if `str` is null: - + ```dart int getLength(String? str) { // Add null check here @@ -233,10 +233,10 @@ void main() { Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. - + ```dart int getLength(String? str) { - // Try throwing here if `str` is null. + // Try throwing exception here if `str` is null. return str.length; } From 47076cf46571d2b30d9d1e027501768d0cdaa897 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:34:56 -0800 Subject: [PATCH 19/80] Update null_safety_examples/null_safety_codelab/bin/conditional_access.dart Co-authored-by: Filip Hracek --- .../null_safety_codelab/bin/conditional_access.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart index 2a72ec0cd7..b1db88b2ca 100644 --- a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart +++ b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart @@ -7,7 +7,7 @@ class LittleThing { } void main() { - final BigThing? big = BigThing(); + BigThing? big = BigThing(); print('The value is:'); print(big?.little.fetchInt()); From f05c4b8d730ca057ea05347ff7f400fc2c346251 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:35:10 -0800 Subject: [PATCH 20/80] Update src/codelabs/null-safety.md Co-authored-by: Filip Hracek --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index a363bcf705..5c72b369a0 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -19,7 +19,7 @@ iframe[src^="https://dartpad"] { } -This codelab teaches you about Dart’s null safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be null unless you say they can be. +This codelab teaches you about Dart’s null safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. Using embedded DartPad editors, you can test your knowledge by running example code and completing exercises. To get the most out of this codelab, you should have some knowledge of [basic Dart syntax](/samples). From f90e9c09501c02eaae7619d7fa259302cabb14ad Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:35:24 -0800 Subject: [PATCH 21/80] Update src/codelabs/null-safety.md Co-authored-by: Filip Hracek --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 5c72b369a0..91b3f28e77 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -26,7 +26,7 @@ Using embedded DartPad editors, you can test your knowledge by running example c This codelab covers the following material: * Nullable and non-nullable types. -* How and when to use the null-aware operators: ? and ! +* How and when to use the null-aware operators: `?` and `!` * How the late keyword affects variables and initialization. {{site.alert.note}} From 9e3de22be6dc743b0376bc4e927bbfee3d0e906e Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:35:33 -0800 Subject: [PATCH 22/80] Update src/codelabs/null-safety.md Co-authored-by: Filip Hracek --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 91b3f28e77..669d665a5c 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -27,7 +27,7 @@ This codelab covers the following material: * Nullable and non-nullable types. * How and when to use the null-aware operators: `?` and `!` -* How the late keyword affects variables and initialization. +* How the `late` keyword affects variables and initialization. {{site.alert.note}} This page uses embedded DartPads to display examples and exercises. From 20515329d6fc281d635c72eaa84c0686c242129f Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:35:44 -0800 Subject: [PATCH 23/80] Update src/codelabs/null-safety.md Co-authored-by: Filip Hracek --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 669d665a5c..ce45af3324 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -56,7 +56,7 @@ type String, it will always contain a string. ## Nullable types -If you want a variable of type String to accept any string, or the value null +If you want a variable of type `String` to accept any string, or the value null but nothing else, you give the variable a nullable type by adding a `?` after the type name. For example, a variable of type String? can contain a string, or it can be null. From cd59884260bd38a6885ee2141140b7729a322758 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:44:43 -0800 Subject: [PATCH 24/80] fixes exception sample --- .../null_safety_codelab/bin/promotion_exceptions.dart | 7 ++++--- src/codelabs/null-safety.md | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart index 4356521b6a..316251af27 100644 --- a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart +++ b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart @@ -1,7 +1,7 @@ int getLength(String? str) { - // Try throwing exception here if `str` is null. - if (str == null) { - return Exception("String is null"); + // Try throwing an exception here if `str` is null. + if (str == null) { + throw Exception("String is null"); } return str.length; } @@ -9,3 +9,4 @@ int getLength(String? str) { void main() { print(getLength(null)); } + diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index ce45af3324..349af058f5 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -171,7 +171,7 @@ class LittleThing { } void main() { - final BigThing? big = BigThing(); + BigThing? big = BigThing(); print('The value is:'); print(big.little.fetchInt()); @@ -236,7 +236,7 @@ that throws an `Exception` instead of returning zero. ```dart int getLength(String? str) { - // Try throwing exception here if `str` is null. + // Try throwing an exception here if `str` is null. return str.length; } From 07fa36932dade4d2d63f21ecfef597b72c344e83 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 19:54:11 -0800 Subject: [PATCH 25/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 349af058f5..04e45aa7a4 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -1,5 +1,5 @@ --- -title: "Null safety" +title: Null safety codelab description: Learn about and practice writing null safe code in DartPad! js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] --- From fa45011d619d0911d735886bb672d4b942faebe5 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 20:00:19 -0800 Subject: [PATCH 26/80] 80-char word wrap & pass for semanatic breaks --- src/codelabs/null-safety.md | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 349af058f5..599d176008 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -4,7 +4,7 @@ description: Learn about and practice writing null safe code in DartPad! js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] --- {% assign useIframe = false -%} - + -This codelab teaches you about Dart’s null safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. +This codelab teaches you about Dart’s null safe type system, +which was introduced in Dart SDK 2.12. When you opt into null safety, +types in your code are non-nullable by default, +meaning that values can’t be `null` unless you say they can be. -Using embedded DartPad editors, you can test your knowledge by running example code and completing exercises. To get the most out of this codelab, you should have some knowledge of [basic Dart syntax](/samples). +Using embedded DartPad editors, you can test your knowledge by +running example code and completing exercises. To get the most out of +this codelab, you should have some knowledge of [basic Dart syntax](/samples). This codelab covers the following material: @@ -37,12 +42,10 @@ This codelab covers the following material: ## What is null safety? -Dart's null safe type system makes types in your code non-nullable by default, -meaning that values can't be null unless you say they can be. Null safety helps +Dart's null safe type system makes types in your code non-nullable by default, meaning that values can't be null unless you say they can be. Null safety helps prevent null reference errors. -Here are some core principles -of sound null safety in the Dart language: +Here are some core principles of sound null safety in the Dart language: - All types are non-nullable by default. - Values can't be null unless you say they can be. @@ -56,10 +59,7 @@ type String, it will always contain a string. ## Nullable types -If you want a variable of type `String` to accept any string, or the value null -but nothing else, you give the variable a nullable type by adding a `?` after -the type name. For example, a variable of type String? can contain a string, or -it can be null. +If you want a variable of type `String` to accept any string, or the value null, but nothing else, you give the variable a nullable type by adding a `?` after the type name. For example, a variable of type `String?` can contain a string, or it can be null. ### Example: Introducing non-nullable types @@ -112,11 +112,10 @@ void main() { Dart's type system is crafty enough to track where variables are assigned and where their values are read, and to verify that non-nullable fields are given -values before any code tries to read from them. This process is called "definite -assignment." +values before any code tries to read from them. This process is called "definite assignment." -Try uncommenting the if-else statement in the code below, and watch the -analyzer errors disappear: +Try uncommenting the if-else statement in the code below, and +watch the analyzer errors disappear: ```dart @@ -143,8 +142,8 @@ Null safety introduces two operators, ? and !. Here's how you use them: non-nullable by default and made nullable by adding ?. - If you're accessing a property and the operand might be null, use the null-aware version member access operator (?.). -- If you're sure that an expression with a nullable type isn't null, you - can add a postfix exclamation mark (!) to make Dart treat it as non-nullable. +- If you're sure that an expression with a nullable type isn't null, you can + add a postfix exclamation mark (!) to make Dart treat it as non-nullable. ### Example: Conditional access @@ -348,7 +347,7 @@ are some suggestions for where to go next: - [Play with DartPad](https://nullsafety.dartpad.dev/). - Try another [codelab](https://dart.dev/codelabs). - Learn more about null safety: - - Overview: [Sound null safety](https://dart.dev/null-safety) + - Overview: [Sound null safety](https://dart.dev/null-safety). - Deep dive: [Understanding null safety](https://dart.dev/null-safety/understanding-null-safety). - [Get the Dart SDK](https://dart.dev/get-dart). From 447222e5afe3d7d28a87a550ed6994c5655c504d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 20:13:03 -0800 Subject: [PATCH 27/80] comments out failing test looking for a package that doesn't exist --- tool/dartformat.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/dartformat.sh b/tool/dartformat.sh index 061ab99d3e..8fd723af75 100755 --- a/tool/dartformat.sh +++ b/tool/dartformat.sh @@ -31,7 +31,7 @@ if [[ $NULL_SAFETY == 1 ]]; then $NULL_SAFETY_EXAMPLES/misc/lib/language_tour/classes/orchestra.dart \ $NULL_SAFETY_EXAMPLES/misc/test/language_tour/built_in_types_test.dart \ $NULL_SAFETY_EXAMPLES/misc/test/language_tour/functions_test.dart \ - $NULL_SAFETY_EXAMPLES/misc/test/library_tour/html_test.dart + # $NULL_SAFETY_EXAMPLES/misc/test/library_tour/html_test.dart # $NULL_SAFETY_EXAMPLES/misc/lib/samples/spacecraft.dart dart format -l 65 \ From 966cd491c1027211396e262e715e8a62c0ef861a Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 20:17:11 -0800 Subject: [PATCH 28/80] one more 80-char fix --- src/codelabs/null-safety.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 3eead172f3..7ddf4ac01f 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -42,7 +42,8 @@ This codelab covers the following material: ## What is null safety? -Dart's null safe type system makes types in your code non-nullable by default, meaning that values can't be null unless you say they can be. Null safety helps +Dart's null safe type system makes types in your code non-nullable by default, +meaning that values can't be null unless you say they can be. Null safety helps prevent null reference errors. Here are some core principles of sound null safety in the Dart language: @@ -59,7 +60,10 @@ type String, it will always contain a string. ## Nullable types -If you want a variable of type `String` to accept any string, or the value null, but nothing else, you give the variable a nullable type by adding a `?` after the type name. For example, a variable of type `String?` can contain a string, or it can be null. +If you want a variable of type `String` to accept any string, or the value null, +but nothing else, you give the variable a nullable type by adding a `?` after the +type name. For example, a variable of type `String?` can contain a string, or +it can be null. ### Example: Introducing non-nullable types @@ -112,7 +116,8 @@ void main() { Dart's type system is crafty enough to track where variables are assigned and where their values are read, and to verify that non-nullable fields are given -values before any code tries to read from them. This process is called "definite assignment." +values before any code tries to read from them. This process is called +"definite assignment." Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: @@ -185,7 +190,8 @@ By adding `!` just after the expression, you tell Dart that the value won't be null, and that it's safe to assign it to a non-nullable variable. If you're wrong, Dart throws an exception. -In the example below, try adding exclamation points to correct the three broken assignments: +In the example below, try adding exclamation points to correct the +three broken assignments: ```dart @@ -208,8 +214,8 @@ void main() { ### Exercise: Type promotion With null safety, Dart takes null checks into account. Nullable variables that -can't possibly contain null are treated like non-nullable variables. This -behavior is called "promotion." +can't possibly contain null are treated like non-nullable variables. +This behavior is called "promotion." In the example below, add an if statement to the beginning of `getLength` that returns zero if `str` is null: From aa09169f14278fb1ce7447c9968ebcc12053ff83 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 20:35:37 -0800 Subject: [PATCH 29/80] . --- .../null_safety_codelab/bin/assertion_operator.dart | 4 ++-- .../null_safety_codelab/bin/conditional_access.dart | 2 +- .../null_safety_codelab/bin/definite_assignment.dart | 2 +- .../null_safety_codelab/bin/late_circular_references.dart | 6 +++--- .../null_safety_codelab/bin/late_keyword.dart | 4 ++-- .../null_safety_codelab/bin/more_nullable_types.dart | 2 +- .../null_safety_codelab/bin/promotion_exceptions.dart | 5 ++--- .../null_safety_codelab/bin/type_promotion.dart | 4 ++-- src/codelabs/null-safety.md | 2 +- 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart index d39e600a96..612b9906b7 100644 --- a/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart +++ b/null_safety_examples/null_safety_codelab/bin/assertion_operator.dart @@ -3,11 +3,11 @@ int? couldReturnNullButDoesnt() => -3; void main() { int? couldBeNullButIsnt = 1; List listThatCouldHoldNulls = [2, null, 4]; - + int a = couldBeNullButIsnt; int b = listThatCouldHoldNulls.first!; // first item in the list int c = couldReturnNullButDoesnt()!.abs(); // absolute value - + print('a is $a.'); print('b is $b.'); print('c is $c.'); diff --git a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart index b1db88b2ca..a399fd3d22 100644 --- a/null_safety_examples/null_safety_codelab/bin/conditional_access.dart +++ b/null_safety_examples/null_safety_codelab/bin/conditional_access.dart @@ -8,7 +8,7 @@ class LittleThing { void main() { BigThing? big = BigThing(); - + print('The value is:'); print(big?.little.fetchInt()); } diff --git a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart index 366d7f28d3..f587459ea3 100644 --- a/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart +++ b/null_safety_examples/null_safety_codelab/bin/definite_assignment.dart @@ -1,6 +1,6 @@ void main() { String text; - + if (DateTime.now().hour < 12) { text = "It's morning! Let's make aloo paratha!"; } else { diff --git a/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart index 146d6ca3dd..7880c4cd41 100644 --- a/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart +++ b/null_safety_examples/null_safety_codelab/bin/late_circular_references.dart @@ -11,6 +11,6 @@ void main() { final myCoach = Coach(); myTeam.coach = myCoach; myCoach.team = myTeam; - - print ('All done!'); -} \ No newline at end of file + + print('All done!'); +} diff --git a/null_safety_examples/null_safety_codelab/bin/late_keyword.dart b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart index 42879bf56e..f1079e2531 100644 --- a/null_safety_examples/null_safety_codelab/bin/late_keyword.dart +++ b/null_safety_examples/null_safety_codelab/bin/late_keyword.dart @@ -1,6 +1,6 @@ class Meal { late String description; - + void setDescription(String str) { description = str; } @@ -10,4 +10,4 @@ void main() { final myMeal = Meal(); myMeal.setDescription('Feijoada!'); print(myMeal.description); -} \ No newline at end of file +} diff --git a/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart index f970023ad1..905e890143 100644 --- a/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart +++ b/null_safety_examples/null_safety_codelab/bin/more_nullable_types.dart @@ -6,4 +6,4 @@ void main() { print('aListofStrings is $aListofStrings.'); print('aNullableListOfStrings is $aNullableListOfStrings.'); print('aListofNullableStrings is $aListofNullableStrings.'); -} \ No newline at end of file +} diff --git a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart index 316251af27..c1ab547536 100644 --- a/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart +++ b/null_safety_examples/null_safety_codelab/bin/promotion_exceptions.dart @@ -1,12 +1,11 @@ int getLength(String? str) { // Try throwing an exception here if `str` is null. - if (str == null) { + if (str == null) { throw Exception("String is null"); } - return str.length; + return str.length; } void main() { print(getLength(null)); } - diff --git a/null_safety_examples/null_safety_codelab/bin/type_promotion.dart b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart index 9b3bfe9f5c..f4ef6356b9 100644 --- a/null_safety_examples/null_safety_codelab/bin/type_promotion.dart +++ b/null_safety_examples/null_safety_codelab/bin/type_promotion.dart @@ -1,9 +1,9 @@ int getLength(String? str) { // Add null check here if (str == null) { - return 0; + return 0; } - return str.length; + return str.length; } void main() { diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 7ddf4ac01f..05792f64d0 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -310,7 +310,7 @@ void main() { myTeam.coach = myCoach; myCoach.team = myTeam; - print ('All done!'); + print('All done!'); } ``` From f146337641b01ea66998d12598a5169dd3b68c8b Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Mon, 22 Feb 2021 20:47:49 -0800 Subject: [PATCH 30/80] . --- src/codelabs/null-safety.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 05792f64d0..d619085370 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -42,9 +42,10 @@ This codelab covers the following material: ## What is null safety? -Dart's null safe type system makes types in your code non-nullable by default, -meaning that values can't be null unless you say they can be. Null safety helps -prevent null reference errors. +Dart's null safe type system makes types in your code non-nullable by default. +That means values in your Dart programs can't be `null` unless you say they can be. +With null safety, you can fix `null` reference errors at edit-type, before you even +run your program. Here are some core principles of sound null safety in the Dart language: From c5242625481be70f229c84bb961ab70327af02c8 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:40:31 -0800 Subject: [PATCH 31/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index d619085370..8cd74ebdf8 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -19,7 +19,7 @@ iframe[src^="https://dartpad"] { } -This codelab teaches you about Dart’s null safe type system, +This codelab teaches you about Dart’s null-safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. From 85ab744a1c1dfa3991a563d4e97558437fff25ca Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:40:40 -0800 Subject: [PATCH 32/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 8cd74ebdf8..64851c724f 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -42,7 +42,7 @@ This codelab covers the following material: ## What is null safety? -Dart's null safe type system makes types in your code non-nullable by default. +Dart's null-safe type system makes types in your code non-nullable by default. That means values in your Dart programs can't be `null` unless you say they can be. With null safety, you can fix `null` reference errors at edit-type, before you even run your program. From a95c04d351fe4ec4851c04aeec5926a9e663a77b Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:40:59 -0800 Subject: [PATCH 33/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 64851c724f..0b29c851be 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -44,7 +44,7 @@ This codelab covers the following material: Dart's null-safe type system makes types in your code non-nullable by default. That means values in your Dart programs can't be `null` unless you say they can be. -With null safety, you can fix `null` reference errors at edit-type, before you even +With null safety, you can find null reference errors before you even run your program. Here are some core principles of sound null safety in the Dart language: From 38378cefb35ed81445a10b677b22d8ffaf407563 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:41:09 -0800 Subject: [PATCH 34/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 0b29c851be..97aaf8d5f5 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -54,7 +54,7 @@ Here are some core principles of sound null safety in the Dart language: - Finding null errors at edit time is much better than finding them at run time. -## Non-nullable types +## Nullable and non-nullable types All types are non-nullable by default. For example, if you have a variable of type String, it will always contain a string. From d16d7799321e296193b1ac6c5f5938b57bc0e7dd Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:41:25 -0800 Subject: [PATCH 35/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 97aaf8d5f5..d372304194 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -56,7 +56,8 @@ Here are some core principles of sound null safety in the Dart language: ## Nullable and non-nullable types -All types are non-nullable by default. For example, if you have a variable of +When you opt into null safety, all types are non-nullable by default. +For example, if you have a variable of type String, it will always contain a string. ## Nullable types From 094793a68fdd396305613416d0d9c5d08a93f4dd Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:41:35 -0800 Subject: [PATCH 36/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index d372304194..fa4be65d05 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -62,8 +62,9 @@ type String, it will always contain a string. ## Nullable types -If you want a variable of type `String` to accept any string, or the value null, -but nothing else, you give the variable a nullable type by adding a `?` after the +If you want a variable of type `String` to accept any string +or the value `null`, but nothing else, +give the variable a nullable type by adding a `?` after the type name. For example, a variable of type `String?` can contain a string, or it can be null. From 473f367f73f18edca540847ad9524e4350365004 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:48:32 -0800 Subject: [PATCH 37/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index fa4be65d05..b7c9f791dc 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -60,7 +60,6 @@ When you opt into null safety, all types are non-nullable by default. For example, if you have a variable of type String, it will always contain a string. -## Nullable types If you want a variable of type `String` to accept any string or the value `null`, but nothing else, From 1d8cd8d29262a96e9b6675a51303cfe47537a538 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:48:45 -0800 Subject: [PATCH 38/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index b7c9f791dc..e7e379fd1f 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -58,7 +58,7 @@ Here are some core principles of sound null safety in the Dart language: When you opt into null safety, all types are non-nullable by default. For example, if you have a variable of -type String, it will always contain a string. +type `String`, it will always contain a string. If you want a variable of type `String` to accept any string From 250662db9e80ca71b7ca21645c30ab45b6ecc75b Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 15:53:13 -0800 Subject: [PATCH 39/80] addresses latest feedback --- src/codelabs/null-safety.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index e7e379fd1f..91b9b65ec0 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -24,16 +24,16 @@ which was introduced in Dart SDK 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. -Using embedded DartPad editors, you can test your knowledge by -running example code and completing exercises. To get the most out of -this codelab, you should have some knowledge of [basic Dart syntax](/samples). - This codelab covers the following material: * Nullable and non-nullable types. * How and when to use the null-aware operators: `?` and `!` * How the `late` keyword affects variables and initialization. +Using embedded DartPad editors, you can test your knowledge by +running example code and completing exercises. To get the most out of +this codelab, you should have some knowledge of [basic Dart syntax](/samples). + {{site.alert.note}} This page uses embedded DartPads to display examples and exercises. {% include dartpads-embedded-troubleshooting.md %} @@ -60,7 +60,6 @@ When you opt into null safety, all types are non-nullable by default. For example, if you have a variable of type `String`, it will always contain a string. - If you want a variable of type `String` to accept any string or the value `null`, but nothing else, give the variable a nullable type by adding a `?` after the @@ -73,7 +72,7 @@ The variable `a` below is declared as an `int`. Try changing the value in the assignment to 3 or 145. Anything but null! -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true void main() { int a; a = null; @@ -87,7 +86,7 @@ What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true void main() { int a; a = null; @@ -102,7 +101,7 @@ question marks to correct the type declarations of `aNullableListOfStrings` and `aListOfNullableStrings`: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true void main() { List aListofStrings = ['one', 'two', 'three']; List aNullableListOfStrings = []; @@ -125,7 +124,7 @@ Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true void main() { String text; @@ -167,7 +166,7 @@ safety, conditional access can short-circuit, so this expression only requires a single `?`: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true class BigThing { LittleThing little = LittleThing(); } @@ -196,7 +195,7 @@ In the example below, try adding exclamation points to correct the three broken assignments: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true int? couldReturnNullButDoesnt() => -3; void main() { @@ -223,7 +222,7 @@ In the example below, add an if statement to the beginning of `getLength` that returns zero if `str` is null: -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true int getLength(String? str) { // Add null check here @@ -241,7 +240,7 @@ Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true int getLength(String? str) { // Try throwing an exception here if `str` is null. @@ -272,7 +271,7 @@ Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true class Meal { String description; @@ -297,7 +296,7 @@ don't have to remove `final`. `late` fields can also be `final`: you set `late final` values once, and after that they're read-only. -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true class Team { final Coach coach; } @@ -323,7 +322,7 @@ expensive non-nullable fields. Try running this code without changing it. What do you think will change if you make `_cache` a `late` field? -```dart +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true int _computeValue() { print('Computing value...'); return 3; From 058bed7f2011d3eabc5ebf6258855119282e3a1b Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Tue, 23 Feb 2021 16:04:24 -0800 Subject: [PATCH 40/80] . --- src/codelabs/null-safety.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 91b9b65ec0..1242f36d3d 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -39,7 +39,6 @@ this codelab, you should have some knowledge of [basic Dart syntax](/samples). {% include dartpads-embedded-troubleshooting.md %} {{site.alert.end}} - ## What is null safety? Dart's null-safe type system makes types in your code non-nullable by default. From 83a85e751e3acbca54fa9ba040b97ce0d5f9cfb0 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:40:10 -0800 Subject: [PATCH 41/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 1242f36d3d..6c8c33da70 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -146,7 +146,7 @@ Null safety introduces two operators, ? and !. Here's how you use them: question mark (?) to the variable's type declaration. Types are non-nullable by default and made nullable by adding ?. - If you're accessing a property and the operand might be null, use the - null-aware version member access operator (?.). + conditional member access operator (`?.`). - If you're sure that an expression with a nullable type isn't null, you can add a postfix exclamation mark (!) to make Dart treat it as non-nullable. From 05e8590c9f5cdc6575d82feac8205bcd2475f440 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:40:18 -0800 Subject: [PATCH 42/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 6c8c33da70..9e6ffe34ca 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -148,7 +148,7 @@ Null safety introduces two operators, ? and !. Here's how you use them: - If you're accessing a property and the operand might be null, use the conditional member access operator (`?.`). - If you're sure that an expression with a nullable type isn't null, you can - add a postfix exclamation mark (!) to make Dart treat it as non-nullable. + add a postfix exclamation mark (`!`) to make Dart treat it as non-nullable. ### Example: Conditional access From 7345b8940f49a1774b7d3df156e46bc3728ac631 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:40:26 -0800 Subject: [PATCH 43/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 9e6ffe34ca..a7af048ea2 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -157,7 +157,8 @@ properties that could be null. For example, the following expression evaluates to the value of `b` as long as `a` isn't null. If `a` is null, then the expression evaluates to null: - a?.b +```dart +a?.b Without null safety, *two* conditional access operators are needed for the following code to work: one after `big` and one after `little`. With null From be97864befe0f006f652c0975ae04927cdb15104 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:42:02 -0800 Subject: [PATCH 44/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index a7af048ea2..0f6203d5bd 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -183,7 +183,7 @@ void main() { } ``` -### Example: The assertion operator `!` +### Example: The assertion operator (!) If you'd like to assign a nullable expression to a variable that's non-nullable, you can use the assertion operator (the exclamation point: `!`). From 59d1d817edda9bc519feccc59a3ca6154b2f75b7 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:44:22 -0800 Subject: [PATCH 45/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 0f6203d5bd..ba0a57f1c6 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -138,7 +138,7 @@ void main() { } ``` -## New null-aware operators: ? and ! +## Using ?. and ! Null safety introduces two operators, ? and !. Here's how you use them: From 12800f1b983dbc50ef767a614afc2c4799554fab Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 09:44:36 -0800 Subject: [PATCH 46/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index ba0a57f1c6..8a8d011b5b 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -142,9 +142,6 @@ void main() { Null safety introduces two operators, ? and !. Here's how you use them: -- If you're creating a variable that can have the value null, add a - question mark (?) to the variable's type declaration. Types are - non-nullable by default and made nullable by adding ?. - If you're accessing a property and the operand might be null, use the conditional member access operator (`?.`). - If you're sure that an expression with a nullable type isn't null, you can From bffd7d6f3c7cccfc49df0b338d30b3d45c964c39 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 10:14:56 -0800 Subject: [PATCH 47/80] addresses latest feedback; removes conditional access section; rewrites section about operators/keywords; adds section about type promotion; moves section about late above section about type promotion --- src/codelabs/null-safety.md | 129 ++++++++++++++---------------------- 1 file changed, 51 insertions(+), 78 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 8a8d011b5b..448e97ce4e 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -61,7 +61,7 @@ type `String`, it will always contain a string. If you want a variable of type `String` to accept any string or the value `null`, but nothing else, -give the variable a nullable type by adding a `?` after the +give the variable a nullable type by adding a question mark (`?`) after the type name. For example, a variable of type `String?` can contain a string, or it can be null. @@ -138,47 +138,18 @@ void main() { } ``` -## Using ?. and ! +## Using ?, !, and late -Null safety introduces two operators, ? and !. Here's how you use them: +Null safety introduces new operators and keywords for dealing with null values, +`?`, `!`, and `late`. Here's how you use them: -- If you're accessing a property and the operand might be null, use the - conditional member access operator (`?.`). +- If you're creating a variable that can hold a null value, you can use a + `?` to inform Dart of the variable’s nullability. - If you're sure that an expression with a nullable type isn't null, you can add a postfix exclamation mark (`!`) to make Dart treat it as non-nullable. - -### Example: Conditional access - -Conditional access is a handy way to tighten up code that needs to read -properties that could be null. For example, the following expression evaluates -to the value of `b` as long as `a` isn't null. If `a` is null, then the -expression evaluates to null: - -```dart -a?.b - -Without null safety, *two* conditional access operators are needed for the -following code to work: one after `big` and one after `little`. With null -safety, conditional access can short-circuit, so this expression only requires a -single `?`: - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -class BigThing { - LittleThing little = LittleThing(); -} - -class LittleThing { - int fetchInt() => 12; -} - -void main() { - BigThing? big = BigThing(); - - print('The value is:'); - print(big.little.fetchInt()); -} -``` +- If you want to initalize a non-nullable variable to a + non-null value before it’s used, insert `late` before the + variable’s type. ### Example: The assertion operator (!) @@ -209,46 +180,6 @@ void main() { } ``` -### Exercise: Type promotion - -With null safety, Dart takes null checks into account. Nullable variables that -can't possibly contain null are treated like non-nullable variables. -This behavior is called "promotion." - -In the example below, add an if statement to the beginning of `getLength` that -returns zero if `str` is null: - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -int getLength(String? str) { - // Add null check here - - return str.length; -} - -void main() { - print(getLength('This is a string!')); -} -``` - -### Exercise: Promotion with exceptions - -Promotion works with exceptions as well as return statements. Try a null check -that throws an `Exception` instead of returning zero. - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -int getLength(String? str) { - // Try throwing an exception here if `str` is null. - - return str.length; -} - -void main() { - print(getLength(null)); -} -``` - ## Late keyword Sometimes fields in a class *should* be non-nullable, but those fields can't be @@ -343,6 +274,48 @@ Fun fact: After you add `late` to the declaration of `_cache`, you can move the still work! Initialization expressions for `late` fields can use instance methods in their initializers. +## Type promotion + +With null safety, Dart takes null checks into account. Nullable variables that +can't possibly contain null are treated like non-nullable variables. +This behavior is called "promotion." + +### Exercise: Null checking + +In the example below, add an if statement to the beginning of `getLength` that +returns zero if `str` is null: + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +int getLength(String? str) { + // Add null check here + + return str.length; +} + +void main() { + print(getLength('This is a string!')); +} +``` + +### Exercise: Promotion with exceptions + +Promotion works with exceptions as well as return statements. Try a null check +that throws an `Exception` instead of returning zero. + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +int getLength(String? str) { + // Try throwing an exception here if `str` is null. + + return str.length; +} + +void main() { + print(getLength(null)); +} +``` + ## What's next? Congratulations, you've finished the codelab! If you'd like to learn more, here From a971ae094f066c0ba143c9a64cbd5a7bf949a4c4 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 10:52:04 -0800 Subject: [PATCH 48/80] removes page-level styling --- src/codelabs/null-safety.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 448e97ce4e..aad370a0a7 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -6,18 +6,6 @@ js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] {% assign useIframe = false -%} - This codelab teaches you about Dart’s null-safe type system, which was introduced in Dart SDK 2.12. When you opt into null safety, From a2236dac7a7adda644902a423252bfc18c01473f Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 24 Feb 2021 11:12:19 -0800 Subject: [PATCH 49/80] moves definite assignment example to type promotion section --- src/codelabs/null-safety.md | 52 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index aad370a0a7..a36507ecc4 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -100,32 +100,6 @@ void main() { } ``` -### Example: Definite assignment - -Dart's type system is crafty enough to track where variables are assigned and -where their values are read, and to verify that non-nullable fields are given -values before any code tries to read from them. This process is called -"definite assignment." - -Try uncommenting the if-else statement in the code below, and -watch the analyzer errors disappear: - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -void main() { - String text; - - //if (DateTime.now().hour < 12) { - // text = "It's morning! Let's make aloo paratha!"; - //} else { - // text = "It's afternoon! Let's make biryani!"; - //} - - print(text); - print(text.length); -} -``` - ## Using ?, !, and late Null safety introduces new operators and keywords for dealing with null values, @@ -268,6 +242,32 @@ With null safety, Dart takes null checks into account. Nullable variables that can't possibly contain null are treated like non-nullable variables. This behavior is called "promotion." +### Example: Definite assignment + +Dart's type system can track where variables are assigned and +where their values are read, and to verify that non-nullable fields are given +values before any code tries to read from them. This process is called +"definite assignment." + +Try uncommenting the if-else statement in the code below, and +watch the analyzer errors disappear: + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +void main() { + String text; + + //if (DateTime.now().hour < 12) { + // text = "It's morning! Let's make aloo paratha!"; + //} else { + // text = "It's afternoon! Let's make biryani!"; + //} + + print(text); + print(text.length); +} +``` + ### Exercise: Null checking In the example below, add an if statement to the beginning of `getLength` that From ec71b63a351cf9e62cee33b14fdb614e11f9416d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Fri, 26 Feb 2021 11:40:12 -0800 Subject: [PATCH 50/80] addresses Mit's feedback --- src/codelabs/null-safety.md | 205 +++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 95 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index a36507ecc4..ccc391697c 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -8,14 +8,15 @@ js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] This codelab teaches you about Dart’s null-safe type system, -which was introduced in Dart SDK 2.12. When you opt into null safety, +which was introduced in Dart 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. This codelab covers the following material: -* Nullable and non-nullable types. +* [Nullable and non-nullable types](/null-safety/understanding-null-safety#non-nullable-and-nullable-types). * How and when to use the null-aware operators: `?` and `!` +* Flow analysis and type promotion. * How the `late` keyword affects variables and initialization. Using embedded DartPad editors, you can test your knowledge by @@ -29,12 +30,12 @@ this codelab, you should have some knowledge of [basic Dart syntax](/samples). ## What is null safety? -Dart's null-safe type system makes types in your code non-nullable by default. -That means values in your Dart programs can't be `null` unless you say they can be. -With null safety, you can find null reference errors before you even +With sound null safety, types are non-nullable by default. +That means values in your Dart programs can't be `null` unless you say they +can be. With null safety, you can find null reference errors before you even run your program. -Here are some core principles of sound null safety in the Dart language: +The core traits of sound null safety in Dart are: - All types are non-nullable by default. - Values can't be null unless you say they can be. @@ -43,15 +44,14 @@ Here are some core principles of sound null safety in the Dart language: ## Nullable and non-nullable types -When you opt into null safety, all types are non-nullable by default. -For example, if you have a variable of +When you [opt in to null safety](/null-safety#enable-null-safety), all types are +non-nullable by default. For example, if you have a variable of type `String`, it will always contain a string. If you want a variable of type `String` to accept any string -or the value `null`, but nothing else, -give the variable a nullable type by adding a question mark (`?`) after the -type name. For example, a variable of type `String?` can contain a string, or -it can be null. +or the value `null`, give the variable a nullable type by adding a +question mark (`?`) after the type name. For example, a variable of +type `String?` can contain a string, or it can be null. ### Example: Introducing non-nullable types @@ -105,21 +105,27 @@ void main() { Null safety introduces new operators and keywords for dealing with null values, `?`, `!`, and `late`. Here's how you use them: -- If you're creating a variable that can hold a null value, you can use a - `?` to inform Dart of the variable’s nullability. -- If you're sure that an expression with a nullable type isn't null, you can - add a postfix exclamation mark (`!`) to make Dart treat it as non-nullable. +- If you're creating a variable that can hold a null value, use a + question mark (`?`) to inform Dart of the variable’s nullability. +- If you're sure that an expression with a nullable type isn't null, use a + postfix exclamation mark (`!`, or "bang operator") to + make Dart treat it as non-nullable. - If you want to initalize a non-nullable variable to a - non-null value before it’s used, insert `late` before the + non-null value before it’s used, use the `late` keyboard before the variable’s type. ### Example: The assertion operator (!) If you'd like to assign a nullable expression to a variable that's -non-nullable, you can use the assertion operator (the exclamation point: `!`). -By adding `!` just after the expression, you tell Dart that the value won't be -null, and that it's safe to assign it to a non-nullable variable. If you're -wrong, Dart throws an exception. +non-nullable, you can use the +[null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) +(the exclamation point: `!`). By adding `!` just after the expression, +you tell Dart that the value won't be null, and that it's safe to assign it to a +non-nullable variable. + +But if you're wrong, Dart throws an exception at run-time. This makes the +`!` operator unsafe, and you should only use it when you are very sure that the +expression isn't null. In the example below, try adding exclamation points to correct the three broken assignments: @@ -142,10 +148,83 @@ void main() { } ``` +## Type promotion + +With sound null safety, Dart's +[flow analysis](/null-safety/understanding-null-safety#flow-analysis) has +been extended to take nullability into account. Nullable variables that +can't possibly contain null values are treated like non-nullable variables. +This behavior is called +[type promotion](/null-safety/understanding-null-safety#type-promotion-on-null-checks). + +### Example: Definite assignment + +Dart's type system can track where variables are assigned and +where their values are read, and to verify that non-nullable fields are given +values before any code tries to read from them. This process is called +[definite assignment](/null-safety/understanding-null-safety#definite-assignment-analysis). + +Try uncommenting the if-else statement in the code below, and +watch the analyzer errors disappear: + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +void main() { + String text; + + //if (DateTime.now().hour < 12) { + // text = "It's morning! Let's make aloo paratha!"; + //} else { + // text = "It's afternoon! Let's make biryani!"; + //} + + print(text); + print(text.length); +} +``` + +### Exercise: Null checking + +In the example below, add an if statement to the beginning of `getLength` that +returns zero if `str` is null: + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +int getLength(String? str) { + // Add null check here + + return str.length; +} + +void main() { + print(getLength('This is a string!')); +} +``` + +### Exercise: Promotion with exceptions + +Promotion works with exceptions as well as return statements. Try a null check +that throws an `Exception` instead of returning zero. + + +```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +int getLength(String? str) { + // Try throwing an exception here if `str` is null. + + return str.length; +} + +void main() { + print(getLength(null)); +} +``` + ## Late keyword Sometimes fields in a class *should* be non-nullable, but those fields can't be -assigned a value immediately. For cases like that, use the `late` keyword. +assigned a value immediately. For cases like that, use the +[`late` keyword]( /null-safety/understanding-null-safety#late-variables). + `late` is how you tell Dart that: - You aren't going to assign that field a value right away. @@ -181,9 +260,11 @@ void main() { The `late` keyword is really helpful for tricky patterns like circular references. Here are two objects that need to maintain non-nullable references -to each other. Try using the `late` keyword to fix this code. Note that you -don't have to remove `final`. `late` fields can also be `final`: you set `late -final` values once, and after that they're read-only. +to each other. Try using the `late` keyword to fix this code. + +Note that you don't need to remove `final`. You can create +[`late final` variables](/null-safety/understanding-null-safety#late-final-variables): +you set their values once, and after that they're read-only. ```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true @@ -207,9 +288,10 @@ void main() { ### Exercise: Late and lazy -Here's another pattern that `late` can help with: lazy initialization for -expensive non-nullable fields. Try running this code without changing it. What -do you think will change if you make `_cache` a `late` field? +Here's another pattern that `late` can help with: +[lazy initialization](/null-safety/understanding-null-safety#lazy-initialization) +for expensive non-nullable fields. Try running this code without changing it. +What do you think will change if you make `_cache` a `late` field? ```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true @@ -236,73 +318,6 @@ Fun fact: After you add `late` to the declaration of `_cache`, you can move the still work! Initialization expressions for `late` fields can use instance methods in their initializers. -## Type promotion - -With null safety, Dart takes null checks into account. Nullable variables that -can't possibly contain null are treated like non-nullable variables. -This behavior is called "promotion." - -### Example: Definite assignment - -Dart's type system can track where variables are assigned and -where their values are read, and to verify that non-nullable fields are given -values before any code tries to read from them. This process is called -"definite assignment." - -Try uncommenting the if-else statement in the code below, and -watch the analyzer errors disappear: - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -void main() { - String text; - - //if (DateTime.now().hour < 12) { - // text = "It's morning! Let's make aloo paratha!"; - //} else { - // text = "It's afternoon! Let's make biryani!"; - //} - - print(text); - print(text.length); -} -``` - -### Exercise: Null checking - -In the example below, add an if statement to the beginning of `getLength` that -returns zero if `str` is null: - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -int getLength(String? str) { - // Add null check here - - return str.length; -} - -void main() { - print(getLength('This is a string!')); -} -``` - -### Exercise: Promotion with exceptions - -Promotion works with exceptions as well as return statements. Try a null check -that throws an `Exception` instead of returning zero. - - -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true -int getLength(String? str) { - // Try throwing an exception here if `str` is null. - - return str.length; -} - -void main() { - print(getLength(null)); -} -``` ## What's next? From 24f27ddfdd05269e839f933b8c6365b529cbcea8 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Fri, 26 Feb 2021 11:46:54 -0800 Subject: [PATCH 51/80] s/Using ?, !, and late/Using ? and 1/ (because we don't talk about late in that section) --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index ccc391697c..64b9d71eb8 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -100,7 +100,7 @@ void main() { } ``` -## Using ?, !, and late +## Using ? and ! Null safety introduces new operators and keywords for dealing with null values, `?`, `!`, and `late`. Here's how you use them: From 2576979494d52ed630e3b6def93d90ea451c43bd Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:28:17 -0800 Subject: [PATCH 52/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 64b9d71eb8..4cc491b8a7 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -219,7 +219,7 @@ void main() { } ``` -## Late keyword +## The late keyword Sometimes fields in a class *should* be non-nullable, but those fields can't be assigned a value immediately. For cases like that, use the From 33ff0f610a8c7862bc90179841cf89f181c7afb6 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:28:44 -0800 Subject: [PATCH 53/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 4cc491b8a7..026e82bdbf 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -15,7 +15,7 @@ meaning that values can’t be `null` unless you say they can be. This codelab covers the following material: * [Nullable and non-nullable types](/null-safety/understanding-null-safety#non-nullable-and-nullable-types). -* How and when to use the null-aware operators: `?` and `!` +* When to add `?` or `!` to indicate nullability or non-nullability * Flow analysis and type promotion. * How the `late` keyword affects variables and initialization. From 515f65946830198f32bc628556b7fc66422132c3 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:03 -0800 Subject: [PATCH 54/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 026e82bdbf..2e1644f6b3 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -1,6 +1,6 @@ --- title: Null safety codelab -description: Learn about and practice writing null safe code in DartPad! +description: Learn about and practice writing null-safe code in DartPad! js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] --- {% assign useIframe = false -%} From 7bedbf0de9fdfeeb81a86fbbe10af6f2e24c1c06 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:10 -0800 Subject: [PATCH 55/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 2e1644f6b3..05b85f4dd0 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -325,7 +325,7 @@ Congratulations, you've finished the codelab! If you'd like to learn more, here are some suggestions for where to go next: - [Play with DartPad](https://nullsafety.dartpad.dev/). -- Try another [codelab](https://dart.dev/codelabs). +- Try another [codelab](/codelabs). - Learn more about null safety: - Overview: [Sound null safety](https://dart.dev/null-safety). - Deep dive: From 3a5bb08df1eb9948d5d4049ddaaa19bf851e2506 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:19 -0800 Subject: [PATCH 56/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 05b85f4dd0..22cadbe224 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -333,4 +333,4 @@ are some suggestions for where to go next: - [Get the Dart SDK](https://dart.dev/get-dart). If you're interested in using embedded DartPads, like this codelab does, see -[best practices for using DartPad in tutorials](https://dart.dev/resources/dartpad-best-practices). +[best practices for using DartPad in tutorials](/resources/dartpad-best-practices). From 602bd466ac85d9f9278d6dc605161a16b2d4361d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:26 -0800 Subject: [PATCH 57/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 22cadbe224..c8673cbbbc 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -330,7 +330,7 @@ are some suggestions for where to go next: - Overview: [Sound null safety](https://dart.dev/null-safety). - Deep dive: [Understanding null safety](https://dart.dev/null-safety/understanding-null-safety). -- [Get the Dart SDK](https://dart.dev/get-dart). +- [Get the Dart SDK](/get-dart). If you're interested in using embedded DartPads, like this codelab does, see [best practices for using DartPad in tutorials](/resources/dartpad-best-practices). From 1e2e9ed18f54dd630e7a6552a97b43385cc89a2e Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:38 -0800 Subject: [PATCH 58/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index c8673cbbbc..1bfce5b07a 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -329,7 +329,7 @@ are some suggestions for where to go next: - Learn more about null safety: - Overview: [Sound null safety](https://dart.dev/null-safety). - Deep dive: - [Understanding null safety](https://dart.dev/null-safety/understanding-null-safety). + [Understanding null safety](/null-safety/understanding-null-safety). - [Get the Dart SDK](/get-dart). If you're interested in using embedded DartPads, like this codelab does, see From 098ca1b244410c6daa36e3059dac2143737a80ec Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:46 -0800 Subject: [PATCH 59/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 1bfce5b07a..8d3f8f8b59 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -327,7 +327,7 @@ are some suggestions for where to go next: - [Play with DartPad](https://nullsafety.dartpad.dev/). - Try another [codelab](/codelabs). - Learn more about null safety: - - Overview: [Sound null safety](https://dart.dev/null-safety). + - Overview: [Sound null safety](/null-safety). - Deep dive: [Understanding null safety](/null-safety/understanding-null-safety). - [Get the Dart SDK](/get-dart). From 97c80d712c7554e0dffa1deb5f88fcd44ddcce4a Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:29:54 -0800 Subject: [PATCH 60/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 8d3f8f8b59..1a00c2da7b 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -7,7 +7,7 @@ js: [{url: 'https://dartpad.dev/inject_embed.dart.js', defer: true}] -This codelab teaches you about Dart’s null-safe type system, +This codelab teaches you about Dart’s [null-safe type system](/null-safety), which was introduced in Dart 2.12. When you opt into null safety, types in your code are non-nullable by default, meaning that values can’t be `null` unless you say they can be. From 6f5f3aad7cc30a9701ba929bb4f84906c8ee7a53 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Thu, 11 Mar 2021 18:30:15 -0800 Subject: [PATCH 61/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 1a00c2da7b..27093a6e40 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -14,7 +14,7 @@ meaning that values can’t be `null` unless you say they can be. This codelab covers the following material: -* [Nullable and non-nullable types](/null-safety/understanding-null-safety#non-nullable-and-nullable-types). +* Nullable and non-nullable types. * When to add `?` or `!` to indicate nullability or non-nullability * Flow analysis and type promotion. * How the `late` keyword affects variables and initialization. From 5df1e059c5a21a6f520e51d08cef3aa0f4221fdd Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:26:11 -0700 Subject: [PATCH 62/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 27093a6e40..38609f6331 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -185,7 +185,7 @@ void main() { ### Exercise: Null checking -In the example below, add an if statement to the beginning of `getLength` that +In the example below, add an `if` statement to the beginning of `getLength` that returns zero if `str` is null: From 360f73e99a66492bfc5056ee2cdbe0182bcddf4d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:26:39 -0700 Subject: [PATCH 63/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 38609f6331..4c056bca8d 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -28,19 +28,6 @@ this codelab, you should have some knowledge of [basic Dart syntax](/samples). {% include dartpads-embedded-troubleshooting.md %} {{site.alert.end}} -## What is null safety? - -With sound null safety, types are non-nullable by default. -That means values in your Dart programs can't be `null` unless you say they -can be. With null safety, you can find null reference errors before you even -run your program. - -The core traits of sound null safety in Dart are: - -- All types are non-nullable by default. -- Values can't be null unless you say they can be. -- Finding null errors at edit time is much better than finding them at run - time. ## Nullable and non-nullable types From 79c32de05a7c045f19a82f9baae8593aa1ff0618 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:27:14 -0700 Subject: [PATCH 64/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 4c056bca8d..d278a3f569 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -68,7 +68,7 @@ void main() { } ``` -### Example: More nullable types! +### Example: Nullable type parameters for generics Type parameters for generics can also be nullable or non-nullable. Try using question marks to correct the type declarations of `aNullableListOfStrings` and From 0ea433cf92bce62f481c4329a4bd954a7eb8d8e8 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:27:29 -0700 Subject: [PATCH 65/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index d278a3f569..776147d919 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -87,7 +87,7 @@ void main() { } ``` -## Using ? and ! +## Using the null assertion operator (!) Null safety introduces new operators and keywords for dealing with null values, `?`, `!`, and `late`. Here's how you use them: From f13c023c9f9b3da417b0f53ae06ee725a3e4f9c3 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:27:49 -0700 Subject: [PATCH 66/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 776147d919..683f20083d 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -89,11 +89,6 @@ void main() { ## Using the null assertion operator (!) -Null safety introduces new operators and keywords for dealing with null values, -`?`, `!`, and `late`. Here's how you use them: - -- If you're creating a variable that can hold a null value, use a - question mark (`?`) to inform Dart of the variable’s nullability. - If you're sure that an expression with a nullable type isn't null, use a postfix exclamation mark (`!`, or "bang operator") to make Dart treat it as non-nullable. From bb57f73490bd1db00226a23907741036e437b66d Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:28:01 -0700 Subject: [PATCH 67/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 683f20083d..ed3e2eb7ff 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -110,7 +110,7 @@ But if you're wrong, Dart throws an exception at run-time. This makes the expression isn't null. In the example below, try adding exclamation points to correct the -three broken assignments: +broken assignments: ```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true From d365d8b11197f75086165fd2252d773538ff8be2 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:28:13 -0700 Subject: [PATCH 68/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index ed3e2eb7ff..81bf13b71e 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -92,9 +92,6 @@ void main() { - If you're sure that an expression with a nullable type isn't null, use a postfix exclamation mark (`!`, or "bang operator") to make Dart treat it as non-nullable. -- If you want to initalize a non-nullable variable to a - non-null value before it’s used, use the `late` keyboard before the - variable’s type. ### Example: The assertion operator (!) From 1744e34a00e757e6057f7aa002f9689d36ccf44f Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:28:30 -0700 Subject: [PATCH 69/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 81bf13b71e..d108d89d24 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -204,7 +204,8 @@ Sometimes fields in a class *should* be non-nullable, but those fields can't be assigned a value immediately. For cases like that, use the [`late` keyword]( /null-safety/understanding-null-safety#late-variables). -`late` is how you tell Dart that: +When you put `late` in front of a variable declaration, +that tells Dart that all of the following are true: - You aren't going to assign that field a value right away. - But you *are* going to assign it a value later. From 033ee338d9e5b715e5b3698a6264d0c7b6d6967c Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:28:42 -0700 Subject: [PATCH 70/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index d108d89d24..2afd2caf72 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -207,9 +207,9 @@ assigned a value immediately. For cases like that, use the When you put `late` in front of a variable declaration, that tells Dart that all of the following are true: -- You aren't going to assign that field a value right away. -- But you *are* going to assign it a value later. -- And you'll make sure it's assigned a value *before* it's accessed. +- Don't assign that variable a value yet. +- You *will* assign it a value later. +- You'll make sure that the variable has a value *before* the variable is used. If you declare a field `late` and the field is read before it is assigned a value, a `LateInitializationError` is thrown to tell you what went wrong. From c462268910598c3b13213265c684e2b2131c3551 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:28:57 -0700 Subject: [PATCH 71/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 2afd2caf72..7661c0fa11 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -200,7 +200,8 @@ void main() { ## The late keyword -Sometimes fields in a class *should* be non-nullable, but those fields can't be +Sometimes variables — fields in a class, or top-level variables — +should be non-nullable, but they can't be assigned a value immediately. For cases like that, use the [`late` keyword]( /null-safety/understanding-null-safety#late-variables). From 661299af31969c68e0e5e7165b60e55ed4f44327 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:29:08 -0700 Subject: [PATCH 72/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 7661c0fa11..3ae42b919c 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -212,7 +212,7 @@ that tells Dart that all of the following are true: - You *will* assign it a value later. - You'll make sure that the variable has a value *before* the variable is used. -If you declare a field `late` and the field is read before it is assigned a +If you declare a variable `late` and the variable is read before it's assigned a value, a `LateInitializationError` is thrown to tell you what went wrong. ### Example: The `late` keyword From 8cbc4200cdb566a1927fcafec5ea42196c795389 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:29:33 -0700 Subject: [PATCH 73/80] Update src/codelabs/null-safety.md Co-authored-by: Kathy Walrath --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 3ae42b919c..e0e648933b 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -305,7 +305,7 @@ methods in their initializers. Congratulations, you've finished the codelab! If you'd like to learn more, here are some suggestions for where to go next: -- [Play with DartPad](https://nullsafety.dartpad.dev/). +- [Play with DartPad]({{site.dartpad}}). - Try another [codelab](/codelabs). - Learn more about null safety: - Overview: [Sound null safety](/null-safety). From 90def0c7e6ff40e4845e1065a57f9c268c4cdcb1 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:41:05 -0700 Subject: [PATCH 74/80] addresses latest feedback --- src/codelabs/null-safety.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index e0e648933b..66a203ae90 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -89,23 +89,18 @@ void main() { ## Using the null assertion operator (!) -- If you're sure that an expression with a nullable type isn't null, use a - postfix exclamation mark (`!`, or "bang operator") to - make Dart treat it as non-nullable. - -### Example: The assertion operator (!) - -If you'd like to assign a nullable expression to a variable that's -non-nullable, you can use the -[null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) -(the exclamation point: `!`). By adding `!` just after the expression, -you tell Dart that the value won't be null, and that it's safe to assign it to a -non-nullable variable. +If you're sure that an expression with a nullable type isn't null, use a +[null asseration operator][null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) +(`!`) to make Dart treat it as non-nullable. By adding `!` just after the +expression, you tell Dart that the value won't be null, and +that it's safe to assign it to a non-nullable variable. But if you're wrong, Dart throws an exception at run-time. This makes the `!` operator unsafe, and you should only use it when you are very sure that the expression isn't null. +### Example: Practice using assertion operator + In the example below, try adding exclamation points to correct the broken assignments: @@ -215,7 +210,7 @@ that tells Dart that all of the following are true: If you declare a variable `late` and the variable is read before it's assigned a value, a `LateInitializationError` is thrown to tell you what went wrong. -### Example: The `late` keyword +### Example: Practice with late Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! From ce7e614f9c94f8a0f5c0134da9eb1dc6acfe3227 Mon Sep 17 00:00:00 2001 From: Ryan McGinnis Date: Wed, 17 Mar 2021 06:46:35 -0700 Subject: [PATCH 75/80] nit --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 66a203ae90..2fe6a0d25a 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -210,7 +210,7 @@ that tells Dart that all of the following are true: If you declare a variable `late` and the variable is read before it's assigned a value, a `LateInitializationError` is thrown to tell you what went wrong. -### Example: Practice with late +### Example: Practice using late Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! From 3e8be92e9b310fe7737567e416543f7665fd94a6 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Fri, 19 Mar 2021 19:27:59 -0700 Subject: [PATCH 76/80] Create a different ga_id for each example --- src/codelabs/null-safety.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 2fe6a0d25a..3ca550e0cf 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -60,7 +60,7 @@ What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-nullable_type:null_safety-true void main() { int a; a = null; @@ -75,7 +75,7 @@ question marks to correct the type declarations of `aNullableListOfStrings` and `aListOfNullableStrings`: -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-nullable_type_generics:null_safety-true void main() { List aListofStrings = ['one', 'two', 'three']; List aNullableListOfStrings = []; @@ -105,7 +105,7 @@ In the example below, try adding exclamation points to correct the broken assignments: -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-null_assertion:null_safety-true int? couldReturnNullButDoesnt() => -3; void main() { @@ -142,7 +142,7 @@ Try uncommenting the if-else statement in the code below, and watch the analyzer errors disappear: -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-definite_assignment:null_safety-true void main() { String text; @@ -163,7 +163,7 @@ In the example below, add an `if` statement to the beginning of `getLength` that returns zero if `str` is null: -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-null_checking:null_safety-true int getLength(String? str) { // Add null check here @@ -181,7 +181,7 @@ Promotion works with exceptions as well as return statements. Try a null check that throws an `Exception` instead of returning zero. -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-promotion_exceptions:null_safety-true int getLength(String? str) { // Try throwing an exception here if `str` is null. @@ -216,7 +216,7 @@ Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-late_keyword:null_safety-true class Meal { String description; @@ -243,7 +243,7 @@ Note that you don't need to remove `final`. You can create you set their values once, and after that they're read-only. -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-late_circular:null_safety-true class Team { final Coach coach; } @@ -270,7 +270,7 @@ for expensive non-nullable fields. Try running this code without changing it. What do you think will change if you make `_cache` a `late` field? -```dart:run-dartpad:ga_id-nonnullable_type:null_safety-true +```dart:run-dartpad:ga_id-lazy_late:null_safety-true int _computeValue() { print('Computing value...'); return 3; From 3419fb795717de9f3fd8994240f93a921b605fe7 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Fri, 19 Mar 2021 19:29:42 -0700 Subject: [PATCH 77/80] Minor tweaks --- src/codelabs/null-safety.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 3ca550e0cf..2ae1a10b6b 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -90,7 +90,7 @@ void main() { ## Using the null assertion operator (!) If you're sure that an expression with a nullable type isn't null, use a -[null asseration operator][null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) +[null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) (`!`) to make Dart treat it as non-nullable. By adding `!` just after the expression, you tell Dart that the value won't be null, and that it's safe to assign it to a non-nullable variable. @@ -99,7 +99,7 @@ But if you're wrong, Dart throws an exception at run-time. This makes the `!` operator unsafe, and you should only use it when you are very sure that the expression isn't null. -### Example: Practice using assertion operator +### Example: Practice using the assertion operator In the example below, try adding exclamation points to correct the broken assignments: From 7b9ab3d7e3c01d590f6cc8262b1b3fbdd4400df7 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Fri, 19 Mar 2021 21:27:27 -0700 Subject: [PATCH 78/80] final cleanup? Copy edit-level stuff, plus changed the last example slightly. --- .../null_safety_codelab/bin/late_lazy.dart | 2 +- src/codelabs/null-safety.md | 66 +++++++++++-------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/null_safety_examples/null_safety_codelab/bin/late_lazy.dart b/null_safety_examples/null_safety_codelab/bin/late_lazy.dart index 016e07914e..2cd87dc773 100644 --- a/null_safety_examples/null_safety_codelab/bin/late_lazy.dart +++ b/null_safety_examples/null_safety_codelab/bin/late_lazy.dart @@ -1,5 +1,5 @@ int _computeValue() { - print('Computing value...'); + print('In _computeValue...'); return 3; } diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index 2ae1a10b6b..ea0c28f62c 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -40,7 +40,7 @@ or the value `null`, give the variable a nullable type by adding a question mark (`?`) after the type name. For example, a variable of type `String?` can contain a string, or it can be null. -### Example: Introducing non-nullable types +### Exercise: Non-nullable types The variable `a` below is declared as an `int`. Try changing the value in the assignment to 3 or 145. Anything but null! @@ -54,7 +54,7 @@ void main() { } ``` -### Example: Nullable types +### Exercise: Nullable types What if you need a variable that *can* hold a null value? Try changing the type of `a` so that `a` can be either null or an int: @@ -68,7 +68,7 @@ void main() { } ``` -### Example: Nullable type parameters for generics +### Exercise: Nullable type parameters for generics Type parameters for generics can also be nullable or non-nullable. Try using question marks to correct the type declarations of `aNullableListOfStrings` and @@ -87,19 +87,21 @@ void main() { } ``` -## Using the null assertion operator (!) +## The null assertion operator (!) -If you're sure that an expression with a nullable type isn't null, use a +If you're sure that an expression with a nullable type isn't null, you can use a [null assertion operator](/null-safety/understanding-null-safety#null-assertion-operator) (`!`) to make Dart treat it as non-nullable. By adding `!` just after the expression, you tell Dart that the value won't be null, and that it's safe to assign it to a non-nullable variable. -But if you're wrong, Dart throws an exception at run-time. This makes the -`!` operator unsafe, and you should only use it when you are very sure that the -expression isn't null. +{{ site.alert.warn }} + If you're wrong, **Dart throws an exception at run-time**. This makes the + `!` operator unsafe, so don't use it unless you're very sure that the + expression isn't null. +{{ site.alert.end }} -### Example: Practice using the assertion operator +### Exercise: Null assertion In the example below, try adding exclamation points to correct the broken assignments: @@ -131,14 +133,14 @@ can't possibly contain null values are treated like non-nullable variables. This behavior is called [type promotion](/null-safety/understanding-null-safety#type-promotion-on-null-checks). -### Example: Definite assignment +### Exercise: Definite assignment Dart's type system can track where variables are assigned and -where their values are read, and to verify that non-nullable fields are given +read, and can verify that non-nullable fields are given values before any code tries to read from them. This process is called [definite assignment](/null-safety/understanding-null-safety#definite-assignment-analysis). -Try uncommenting the if-else statement in the code below, and +Try uncommenting the `if`-`else` statement in the code below, and watch the analyzer errors disappear: @@ -201,16 +203,16 @@ assigned a value immediately. For cases like that, use the [`late` keyword]( /null-safety/understanding-null-safety#late-variables). When you put `late` in front of a variable declaration, -that tells Dart that all of the following are true: +that tells Dart the following: - Don't assign that variable a value yet. - You *will* assign it a value later. - You'll make sure that the variable has a value *before* the variable is used. If you declare a variable `late` and the variable is read before it's assigned a -value, a `LateInitializationError` is thrown to tell you what went wrong. +value, a `LateInitializationError` is thrown. -### Example: Practice using late +### Exercise: Using late Try using the `late` keyword to correct the following code. For a little extra fun afterward, try commenting out the line that sets `description`! @@ -232,10 +234,10 @@ void main() { } ``` -### Example: Late circular references +### Exercise: Late circular references -The `late` keyword is really helpful for tricky patterns like circular -references. Here are two objects that need to maintain non-nullable references +The `late` keyword is helpful for tricky patterns like circular references. +The following code has two objects that need to maintain non-nullable references to each other. Try using the `late` keyword to fix this code. Note that you don't need to remove `final`. You can create @@ -266,13 +268,21 @@ void main() { Here's another pattern that `late` can help with: [lazy initialization](/null-safety/understanding-null-safety#lazy-initialization) -for expensive non-nullable fields. Try running this code without changing it. -What do you think will change if you make `_cache` a `late` field? +for expensive non-nullable fields. +Try this: + +
    +
  1. Run this code without changing it, and note the output.
  2. +
  3. Think: What will change if + you make _cache a late field?
  4. +
  5. Make _cache a late field, and run the code. + Was your prediction correct?
  6. +
```dart:run-dartpad:ga_id-lazy_late:null_safety-true int _computeValue() { - print('Computing value...'); + print('In _computeValue...'); return 3; } @@ -289,10 +299,13 @@ void main() { } ``` -Fun fact: After you add `late` to the declaration of `_cache`, you can move the -`_computeValue` function into the `CachedValueProvider` class and the code will -still work! Initialization expressions for `late` fields can use instance -methods in their initializers. +{{ site.alert.info }} + **Fun fact:** + After you add `late` to the declaration of `_cache`, if you move the + `_computeValue` function into the `CachedValueProvider` class the code + still works! Initialization expressions for `late` fields can use instance + methods in their initializers. +{{ site.alert.end }} ## What's next? @@ -300,12 +313,11 @@ methods in their initializers. Congratulations, you've finished the codelab! If you'd like to learn more, here are some suggestions for where to go next: -- [Play with DartPad]({{site.dartpad}}). -- Try another [codelab](/codelabs). - Learn more about null safety: - Overview: [Sound null safety](/null-safety). - Deep dive: [Understanding null safety](/null-safety/understanding-null-safety). +- Try another [codelab](/codelabs). - [Get the Dart SDK](/get-dart). If you're interested in using embedded DartPads, like this codelab does, see From 2b94c361111758abdd93ee7a4830b91cd8f55bd2 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Sat, 20 Mar 2021 14:22:30 -0700 Subject: [PATCH 79/80] Remove references to examples (they're all exercises) --- src/codelabs/null-safety.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index ea0c28f62c..fcf8557d56 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -20,11 +20,11 @@ This codelab covers the following material: * How the `late` keyword affects variables and initialization. Using embedded DartPad editors, you can test your knowledge by -running example code and completing exercises. To get the most out of +completing and running exercises. To get the most out of this codelab, you should have some knowledge of [basic Dart syntax](/samples). {{site.alert.note}} - This page uses embedded DartPads to display examples and exercises. + This page uses embedded DartPads to display exercises. {% include dartpads-embedded-troubleshooting.md %} {{site.alert.end}} @@ -103,7 +103,7 @@ that it's safe to assign it to a non-nullable variable. ### Exercise: Null assertion -In the example below, try adding exclamation points to correct the +In the code below, try adding exclamation points to correct the broken assignments: @@ -161,7 +161,7 @@ void main() { ### Exercise: Null checking -In the example below, add an `if` statement to the beginning of `getLength` that +In the code below, add an `if` statement to the beginning of `getLength` that returns zero if `str` is null: From 31c99f302286a78f1b33f80180541b38783f9ed8 Mon Sep 17 00:00:00 2001 From: Kathy Walrath Date: Mon, 22 Mar 2021 16:46:11 -0700 Subject: [PATCH 80/80] LateInitializationError -> error Co-authored-by: Parker Lougheed --- src/codelabs/null-safety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codelabs/null-safety.md b/src/codelabs/null-safety.md index fcf8557d56..3ff734a1c1 100644 --- a/src/codelabs/null-safety.md +++ b/src/codelabs/null-safety.md @@ -210,7 +210,7 @@ that tells Dart the following: - You'll make sure that the variable has a value *before* the variable is used. If you declare a variable `late` and the variable is read before it's assigned a -value, a `LateInitializationError` is thrown. +value, an error is thrown. ### Exercise: Using late