1
1
---
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
4
4
js : [{url: '/assets/js/inject_dartpad.js', defer: true}]
5
5
---
6
6
<? 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.
11
11
This codelab walks you through
12
12
the most important of these language features.
13
13
14
- The embedded editors in this codelab have partially completed code snippets.
14
+ The embedded editors in this cheatsheet have partially completed code snippets.
15
15
You can use these editors to test your knowledge by completing the code and
16
16
clicking the ** Run** button. The editors also contain thorough test code;
17
17
** 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.
114
114
To learn more about null safety in Dart,
115
115
read the [ sound null safety guide] ( /null-safety ) .
116
116
117
-
118
117
### Code example {:.no_toc}
119
118
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 ` .
123
123
124
124
Ignore all initial errors in the DartPad.
125
125
@@ -157,7 +157,6 @@ void main() {
157
157
158
158
</details >
159
159
160
-
161
160
## Null-aware operators
162
161
163
162
Dart offers some handy operators for dealing with values that might be null. One is the
@@ -1180,9 +1179,10 @@ void main() {
1180
1179
1181
1180
## Exceptions
1182
1181
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.
1186
1186
1187
1187
Dart provides ` Exception ` and ` Error ` types, but you're
1188
1188
allowed to throw any non-null object:
@@ -1273,12 +1273,17 @@ abstract class Logger {
1273
1273
}
1274
1274
1275
1275
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
+ }
1279
1285
}
1280
1286
1281
-
1282
1287
// Tests your solution (Don't edit!):
1283
1288
class MyLogger extends Logger {
1284
1289
Type? lastType;
@@ -1755,17 +1760,19 @@ class Shape {
1755
1760
1756
1761
### Code example {:.no_toc}
1757
1762
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:
1760
1765
1761
1766
* If the list has ** one** value,
1762
- create an ` IntegerSingle ` with that value.
1767
+ create an ` IntegerSingle ` instance using that value.
1763
1768
* 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.
1765
1770
* 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.
1767
1772
* Otherwise, throw an ` Error ` .
1768
1773
1774
+ If you succeed, the console should display ` Success! ` .
1775
+
1769
1776
``` dartpad
1770
1777
class IntegerHolder {
1771
1778
IntegerHolder();
@@ -1778,107 +1785,99 @@ class IntegerHolder {
1778
1785
1779
1786
class IntegerSingle extends IntegerHolder {
1780
1787
final int a;
1781
- IntegerSingle(this.a);
1788
+
1789
+ IntegerSingle(this.a);
1782
1790
}
1783
1791
1784
1792
class IntegerDouble extends IntegerHolder {
1785
1793
final int a;
1786
1794
final int b;
1787
- IntegerDouble(this.a, this.b);
1795
+
1796
+ IntegerDouble(this.a, this.b);
1788
1797
}
1789
1798
1790
1799
class IntegerTriple extends IntegerHolder {
1791
1800
final int a;
1792
1801
final int b;
1793
1802
final int c;
1794
- IntegerTriple(this.a, this.b, this.c);
1795
- }
1796
1803
1804
+ IntegerTriple(this.a, this.b, this.c);
1805
+ }
1797
1806
1798
- // Tests your solution (Don't edit! ):
1807
+ // Tests your solution (Don't edit from this point to end of file ):
1799
1808
void main() {
1800
1809
final errs = <String>[];
1801
1810
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;
1813
1814
}
1814
-
1815
- if (!_throwed) {
1816
- errs.add('Called IntegerSingle.fromList([]) and didn\'t throw Error.');
1817
- }
1818
1815
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);
1832
1825
}
1826
+ }
1833
1827
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})";
1834
1832
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;
1848
1840
} 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
+ }
1851
1849
}
1850
+ return true;
1851
+ }
1852
1852
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;
1858
1867
} 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.");
1870
1870
}
1871
- } catch (e) {
1872
- print('Called IntegerHolder.fromList([1, 2, 3]) and got an exception \n of type ${e.runtimeType}.');
1873
- return;
1874
- }
1875
1871
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
+ }
1880
1878
}
1881
1879
}
1880
+
1882
1881
```
1883
1882
1884
1883
<details >
@@ -1888,17 +1887,18 @@ void main() {
1888
1887
check the length of the list, then create and return an
1889
1888
` IntegerSingle ` , ` IntegerDouble ` , or ` IntegerTriple ` as appropriate.
1890
1889
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:
1894
1895
return IntegerSingle(list[0]);
1895
- } else if (list.length == 2) {
1896
+ case 2:
1896
1897
return IntegerDouble(list[0], list[1]);
1897
- } else if (list.length == 3) {
1898
+ case 3:
1898
1899
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.");
1902
1902
}
1903
1903
```
1904
1904
@@ -2084,9 +2084,10 @@ void main() {
2084
2084
2085
2085
## What's next?
2086
2086
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
2088
2088
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:
2090
2091
2091
2092
* Try [ other Dart codelabs] ( /codelabs ) .
2092
2093
* Read the [ Dart language tour] ( /language ) .
0 commit comments