Skip to content

Commit 8574066

Browse files
authored
Fix factory constructor example (#5889)
Fixes #5615 Fixes #5616
1 parent dc7c42c commit 8574066

File tree

1 file changed

+103
-102
lines changed

1 file changed

+103
-102
lines changed

src/content/codelabs/dart-cheatsheet.md

+103-102
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
title: Dart cheatsheet codelab
3-
description: Interactively learn (or relearn) some of Dart's unique features.
2+
title: Dart cheatsheet
3+
description: Learn some of Dart's unique features through DartPad
44
js: [{url: '/assets/js/inject_dartpad.js', defer: true}]
55
---
66
<?code-excerpt replace="/ *\/\/\s+ignore_for_file:[^\n]+\n//g; /(^|\n) *\/\/\s+ignore:[^\n]+\n/$1/g; /(\n[^\n]+) *\/\/\s+ignore:[^\n]+\n/$1\n/g"?>
@@ -11,7 +11,7 @@ but it has a few unique features.
1111
This codelab walks you through
1212
the most important of these language features.
1313

14-
The embedded editors in this codelab have partially completed code snippets.
14+
The embedded editors in this cheatsheet have partially completed code snippets.
1515
You can use these editors to test your knowledge by completing the code and
1616
clicking the **Run** button. The editors also contain thorough test code;
1717
**don't edit the test code**, but feel free to study it to learn about testing.
@@ -114,12 +114,12 @@ int? a; // The initial value of a is null.
114114
To learn more about null safety in Dart,
115115
read the [sound null safety guide](/null-safety).
116116

117-
118117
### Code example {:.no_toc}
119118

120-
Try to declare two variables below:
121-
- A nullable `String` named `name` with the value `'Jane'`.
122-
- A nullable `String` named `address` with the value `null`.
119+
Declare two variables in this DartPad:
120+
121+
* A nullable `String` named `name` with the value `'Jane'`.
122+
* A nullable `String` named `address` with the value `null`.
123123

124124
Ignore all initial errors in the DartPad.
125125

@@ -157,7 +157,6 @@ void main() {
157157

158158
</details>
159159

160-
161160
## Null-aware operators
162161

163162
Dart offers some handy operators for dealing with values that might be null. One is the
@@ -1180,9 +1179,10 @@ void main() {
11801179

11811180
## Exceptions
11821181

1183-
Dart code can throw and catch exceptions. In contrast to Java, all of Dart's exceptions are unchecked
1184-
exceptions. Methods don't declare which exceptions they might throw, and you aren't required to catch
1185-
any exceptions.
1182+
Dart code can throw and catch exceptions.
1183+
In contrast to Java, all of Dart's exceptions are unchecked.
1184+
Methods don't declare which exceptions they might throw and
1185+
you aren't required to catch any exceptions.
11861186

11871187
Dart provides `Exception` and `Error` types, but you're
11881188
allowed to throw any non-null object:
@@ -1273,12 +1273,17 @@ abstract class Logger {
12731273
}
12741274
12751275
void tryFunction(VoidFunction untrustworthy, Logger logger) {
1276-
// Invoking this method might cause an exception.
1277-
// TODO: Catch and handle them using try-on-catch-finally.
1278-
untrustworthy();
1276+
try {
1277+
untrustworthy();
1278+
} on ExceptionWithMessage catch (e) {
1279+
logger.logException(e.runtimeType, e.message);
1280+
} on Exception catch (e) {
1281+
logger.logException(e.runtimeType);
1282+
} finally {
1283+
logger.doneLogging();
1284+
}
12791285
}
12801286
1281-
12821287
// Tests your solution (Don't edit!):
12831288
class MyLogger extends Logger {
12841289
Type? lastType;
@@ -1755,17 +1760,19 @@ class Shape {
17551760

17561761
### Code example {:.no_toc}
17571762

1758-
Fill in the factory constructor named `IntegerHolder.fromList`,
1759-
making it do the following:
1763+
Replace the line `TODO();` in the factory constructor
1764+
named `IntegerHolder.fromList` to return the following:
17601765

17611766
* If the list has **one** value,
1762-
create an `IntegerSingle` with that value.
1767+
create an `IntegerSingle` instance using that value.
17631768
* If the list has **two** values,
1764-
create an `IntegerDouble` with the values in order.
1769+
create an `IntegerDouble` instance using the values in order.
17651770
* If the list has **three** values,
1766-
create an `IntegerTriple` with the values in order.
1771+
create an `IntegerTriple` instance using the values in order.
17671772
* Otherwise, throw an `Error`.
17681773

1774+
If you succeed, the console should display `Success!`.
1775+
17691776
```dartpad
17701777
class IntegerHolder {
17711778
IntegerHolder();
@@ -1778,107 +1785,99 @@ class IntegerHolder {
17781785
17791786
class IntegerSingle extends IntegerHolder {
17801787
final int a;
1781-
IntegerSingle(this.a);
1788+
1789+
IntegerSingle(this.a);
17821790
}
17831791
17841792
class IntegerDouble extends IntegerHolder {
17851793
final int a;
17861794
final int b;
1787-
IntegerDouble(this.a, this.b);
1795+
1796+
IntegerDouble(this.a, this.b);
17881797
}
17891798
17901799
class IntegerTriple extends IntegerHolder {
17911800
final int a;
17921801
final int b;
17931802
final int c;
1794-
IntegerTriple(this.a, this.b, this.c);
1795-
}
17961803
1804+
IntegerTriple(this.a, this.b, this.c);
1805+
}
17971806
1798-
// Tests your solution (Don't edit!):
1807+
// Tests your solution (Don't edit from this point to end of file):
17991808
void main() {
18001809
final errs = <String>[];
18011810
1802-
bool _throwed = false;
1803-
try {
1804-
IntegerHolder.fromList([]);
1805-
} on UnimplementedError {
1806-
print('Test failed. Did you implement the method?');
1807-
return;
1808-
} on Error {
1809-
_throwed = true;
1810-
} catch (e) {
1811-
print('Called IntegerSingle.fromList([]) and got an exception of \n type ${e.runtimeType}.');
1812-
return;
1811+
// Run 5 tests to see which values have valid integer holders
1812+
for (var tests = 0; tests < 5; tests++) {
1813+
if (!testNumberOfArgs(errs, tests)) return;
18131814
}
1814-
1815-
if (!_throwed) {
1816-
errs.add('Called IntegerSingle.fromList([]) and didn\'t throw Error.');
1817-
}
18181815
1819-
try {
1820-
final obj = IntegerHolder.fromList([1]);
1821-
1822-
if (obj is! IntegerSingle) {
1823-
errs.add('Called IntegerHolder.fromList([1]) and got an object of type \n ${obj.runtimeType} instead of IntegerSingle.');
1824-
} else {
1825-
if (obj.a != 1) {
1826-
errs.add('Called IntegerHolder.fromList([1]) and got an IntegerSingle with \n an \'a\' value of ${obj.a} instead of the expected (1).');
1827-
}
1828-
}
1829-
} catch (e) {
1830-
print('Called IntegerHolder.fromList([]) and got an exception of \n type ${e.runtimeType}.');
1831-
return;
1816+
// The goal is no errors with values 1 to 3,
1817+
// but have errors with values 0 and 4.
1818+
// The testNumberOfArgs method adds to the errs array if
1819+
// the values 1 to 3 have an error and
1820+
// the values 0 and 4 don't have an error
1821+
if (errs.isEmpty) {
1822+
print('Success!');
1823+
} else {
1824+
errs.forEach(print);
18321825
}
1826+
}
18331827
1828+
bool testNumberOfArgs(List<String> errs, int count) {
1829+
bool _threw = false;
1830+
final ex = List.generate(count, (index) => index + 1);
1831+
final callTxt = "IntegerHolder.fromList(${ex})";
18341832
try {
1835-
final obj = IntegerHolder.fromList([1, 2]);
1836-
1837-
if (obj is! IntegerDouble) {
1838-
errs.add('Called IntegerHolder.fromList([1, 2]) and got an object of type \n ${obj.runtimeType} instead of IntegerDouble.');
1839-
} else {
1840-
if (obj.a != 1) {
1841-
errs.add('Called IntegerHolder.fromList([1, 2]) and got an IntegerDouble \n with an \'a\' value of ${obj.a} instead of the expected (1).');
1842-
}
1843-
1844-
if (obj.b != 2) {
1845-
errs.add('Called IntegerHolder.fromList([1, 2]) and got an IntegerDouble \n with an \'b\' value of ${obj.b} instead of the expected (2).');
1846-
}
1847-
}
1833+
final obj = IntegerHolder.fromList(ex);
1834+
final String vals = count == 1 ? "value" : "values";
1835+
// Uncomment the next line if you want to see the results realtime
1836+
// print("Testing with ${count} ${vals} using ${obj.runtimeType}.");
1837+
testValues(errs, ex, obj, callTxt);
1838+
} on Error {
1839+
_threw = true;
18481840
} catch (e) {
1849-
print('Called IntegerHolder.fromList([1, 2]) and got an exception \n of type ${e.runtimeType}.');
1850-
return;
1841+
switch (count) {
1842+
case (< 1 && > 3):
1843+
if (!_threw) {
1844+
errs.add('Called ${callTxt} and it didn\'t throw an Error.');
1845+
}
1846+
default:
1847+
errs.add('Called $callTxt and received an Error.');
1848+
}
18511849
}
1850+
return true;
1851+
}
18521852
1853-
try {
1854-
final obj = IntegerHolder.fromList([1, 2, 3]);
1855-
1856-
if (obj is! IntegerTriple) {
1857-
errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an object of type \n ${obj.runtimeType} instead of IntegerTriple.');
1853+
void testValues(List<String> errs, List<int> expectedValues, IntegerHolder obj,
1854+
String callText) {
1855+
for (var i = 0; i < expectedValues.length; i++) {
1856+
int found;
1857+
if (obj is IntegerSingle) {
1858+
found = obj.a;
1859+
} else if (obj is IntegerDouble) {
1860+
found = i == 0 ? obj.a : obj.b;
1861+
} else if (obj is IntegerTriple) {
1862+
found = i == 0
1863+
? obj.a
1864+
: i == 1
1865+
? obj.b
1866+
: obj.c;
18581867
} else {
1859-
if (obj.a != 1) {
1860-
errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.a} instead of the expected (1).');
1861-
}
1862-
1863-
if (obj.b != 2) {
1864-
errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.b} instead of the expected (2).');
1865-
}
1866-
1867-
if (obj.c != 3) {
1868-
errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.b} instead of the expected (2).');
1869-
}
1868+
throw ArgumentError(
1869+
"This IntegerHolder type (${obj.runtimeType}) is unsupported.");
18701870
}
1871-
} catch (e) {
1872-
print('Called IntegerHolder.fromList([1, 2, 3]) and got an exception \n of type ${e.runtimeType}.');
1873-
return;
1874-
}
18751871
1876-
if (errs.isEmpty) {
1877-
print('Success!');
1878-
} else {
1879-
errs.forEach(print);
1872+
if (found != expectedValues[i]) {
1873+
errs.add(
1874+
"Called $callText and got a ${obj.runtimeType} " +
1875+
"with a property at index $i value of $found " +
1876+
"instead of the expected (${expectedValues[i]}).");
1877+
}
18801878
}
18811879
}
1880+
18821881
```
18831882

18841883
<details>
@@ -1888,17 +1887,18 @@ void main() {
18881887
check the length of the list, then create and return an
18891888
`IntegerSingle`, `IntegerDouble`, or `IntegerTriple` as appropriate.
18901889

1891-
```dart
1892-
factory IntegerHolder.fromList(List<int> list) {
1893-
if (list.length == 1) {
1890+
Replace `TODO();` with the following code block.
1891+
1892+
```dart
1893+
switch (list.length) {
1894+
case 1:
18941895
return IntegerSingle(list[0]);
1895-
} else if (list.length == 2) {
1896+
case 2:
18961897
return IntegerDouble(list[0], list[1]);
1897-
} else if (list.length == 3) {
1898+
case 3:
18981899
return IntegerTriple(list[0], list[1], list[2]);
1899-
} else {
1900-
throw Error();
1901-
}
1900+
default:
1901+
throw ArgumentError("List must between 1 and 3 items. This list was ${list.length} items.");
19021902
}
19031903
```
19041904

@@ -2084,9 +2084,10 @@ void main() {
20842084

20852085
## What's next?
20862086

2087-
We hope you enjoyed using this codelab to learn or test your knowledge of
2087+
We hope you enjoyed using this cheatsheet to learn
20882088
some of the most interesting features of the Dart language.
2089-
Here are some suggestions for what to do now:
2089+
2090+
What you can try next includes:
20902091

20912092
* Try [other Dart codelabs](/codelabs).
20922093
* Read the [Dart language tour](/language).

0 commit comments

Comments
 (0)