Created
May 20, 2020 19:34
-
-
Save C-Rodg/f075671cfc8f96542d72d6e109a7706b to your computer and use it in GitHub Desktop.
Dart Basics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This guide encompasses the basics of the Dart programming language. | |
// It is heavily based off of the Dart guides listed below: | |
// Library Tour: | |
// https://dart.dev/guides/libraries/library-tour | |
// Language Tour: | |
// https://dart.dev/guides/language/language-tour | |
// To further explore any of the code, just head to the site: | |
// https://dartpad.dev/ | |
// This is the main entry point to a Dart application | |
void main() { | |
// do stuff here... | |
} | |
// --------------- Dates Tests ----------------- // | |
void dateTests() { | |
DateTime now = DateTime.now(); | |
DateTime utc = DateTime.now().toUtc(); | |
assert(now.isUtc == false); | |
assert(utc.isUtc == true); | |
// Note: Only ever add durations to UTC times | |
DateTime future = utc.add(new Duration(days: 3)); | |
} | |
// --------------- Collections Tests ----------------- // | |
void collectionTests() { | |
// ------------- LISTS ---------------- // | |
List<String> stringList = ["A", "B", "C"]; | |
stringList.sort(); | |
// Note: calling .toList() forces iterable to become list | |
var lowStrings = stringList.map((c) => c.toLowerCase()).toList(); | |
List<dynamic> dynamicList = []; | |
dynamicList.add(null); | |
dynamicList.add(3); | |
dynamicList.add("Foo"); | |
dynamicList.remove(3); | |
// Looping, mapping, filtering | |
dynamicList.forEach((v) => print(v)); | |
for(String name in stringList) { | |
// do something... | |
} | |
var aboveNine = [3, 22, 15, 2, 10].where((int x) => x >= 10); | |
List<num> allNumbers = [1, 2.528, 3, 72.5]; | |
allNumbers.forEach((num n) { | |
if (n is int) print("INT"); | |
if (n is double) print("DOUBLE"); | |
}) | |
// Spreading | |
List<String> copy1 = ["A", "B", "C"]; | |
List<String> copy2 = ["X", "Y", "Z"]; | |
var copyAll = [...copy1, ...copy2]; | |
print(copyAll.join("")); | |
var copy3; | |
var nullAwareSpread = [...copy1, ...copy2, ...?copy3]; | |
// Adding items conditionally | |
var promoActive = false; | |
var plants = ["Tree", "Flower", if(promoActive) "Bonsai", "Daisy"]; | |
var names = ["Tom", "Jane", "Sally"]; | |
var fullNameList = ["Winston", for(var s in names) "$s"]; | |
// Immutable lists | |
const myFrozenVar = []; | |
myFrozenVar.add("Purple"); // this would fail as it's immutable | |
// if 'const' is declared here then it makes the list immutable but not the variable itself | |
var myFrozenList = const[]; | |
myFrozenList.add("Green"); // error | |
myFrozenList = ["Purple"]; // no error | |
// ------------- MAPS ---------------- // | |
Map<String, Person> mapPerson = Map(); | |
mapPerson["tom"] = Person.name("Tom"); | |
Map<String, Person> mergeMap = {"foo": Person.name("Foo")}; | |
mapPerson.addAll(mergeMap); | |
mapPerson.remove("bot"); | |
mapPerson.remove("tom"); | |
mapPerson["tom"] = Person.name("Tommy"); | |
mapPerson.containsKey("tom"); | |
// add 'tom' only if it doesn't already contain the key | |
mapPerson.putIfAbsent("tom", () => Person.name("TOM")); | |
// looping | |
for(String k in mapPerson.keys) { | |
print(k + ":" + mapPerson[k].getName()); | |
} | |
// ------------- SETS ---------------- // | |
Set<String> mySet = Set(); | |
mySet.add("Blue"); | |
mySet.remove("Green"); | |
mySet.addAll(["Yellow", "Brown"]); | |
mySet.contains("Brown"); | |
mySet.containsAll(["Blue", "Yellow"]); | |
var mySet2 = Set.from(["Red", "Blue", "Red", "Green", "Brown"]); | |
var mySet3 = {"Red", "Green", "Blue"}; | |
var intersection = mySet2.intersection(mySet3); | |
// looping | |
for(String s in mySet) { | |
// use 's'... | |
} | |
} | |
// --------------- Functions Tests ----------------- // | |
void functionTests() { | |
// Declared function | |
int sum(int a, int b) { | |
return a + b; | |
} | |
// Arrow function | |
int sum2(int a, int b) => a + b; | |
// Anonymous function | |
["red", "green", "blue"].forEach((color) { | |
// function body... | |
}); | |
void sayIt(String s) {}; | |
["red", "green", "blue"].forEach(sayIt); | |
// Higher order functions. Note the 'Function' type. | |
Function wrapper() { | |
void innerFunc(String m) { | |
// do something... | |
} | |
return innerFunc; | |
} | |
["red", "green", "blue"].forEach(wrapper()); | |
// -------- Parameter Types --------- // | |
// Named | |
void namedParams({ String name = "", String location }) {} // Note: 'name' uses a default value | |
namedParams(location: "Seattle"); | |
namedParams(name: "Tom", location: "San Francisco"); | |
// Required parameters | |
void requiredTest({ @required String name }) {}; | |
requiredTest(name: "Foo"); | |
// Optional Positional Parameters | |
void optPositional(String beep, [String bop = "BOP"]) {} | |
optPositional("Foo", "Bar"); | |
optPositional("Foo"); | |
} | |
// --------------- String Tests ----------------- // | |
void stringTests() { | |
// Common methods | |
"Football".contains("oo"); | |
"Football".startsWith("Foo"); | |
"Football".endsWith("ll"); | |
"Football".codeUnits.toList(); | |
"".isEmpty; | |
"foo".isNotEmpty; | |
// String builder | |
var sb = StringBuffer(); | |
sb | |
..write("Use a stringbuffer for ") | |
..writeAll(["efficient", "string", "creation"], "") | |
..write("."); | |
var fullString = sb.toString(); | |
// Iteration | |
var str = "Iteratable string"; | |
for(var char in str.split("")) {} | |
// Regex | |
var greetingTemplate = "Hello, NAME!"; | |
var greeting = greetingTemplate.replaceAll(RegExp("NAME"), "Bill"); | |
// Interpolation | |
String name = "Dave"; | |
print("The man named $name says hi!"); | |
print("The sum is: ${2 + 5}.") | |
// Multiline | |
String multi = """ | |
line one | |
line two | |
"""; | |
// Raw string | |
String rawString = r'the newline character in code is \n'; | |
String regEx = r'\d+'; | |
} | |
// --------------- Library Tests ----------------- // | |
void libraryTests() { | |
// Equality: | |
// Note only == is used and not === | |
// Numbers | |
int.parse("0101", radix: 2); | |
123.4567.toStringAsFixed(2); | |
// Cascades | |
// a way to perform multiple operations on one object | |
querySelector("#foo") | |
..text = "Click me!" | |
..classes.add("important") | |
..onClick.listen(sayHi); | |
// Futures | |
Future<void> myAsyncFunction() async { | |
// do some async stuff using 'await' | |
} | |
Future<String> myAsyncString() async => "Foo..."; | |
// Errors | |
// use 'catch' when you need access to the exception object. | |
try { | |
doSomethingBroken(); | |
} on SomeCustomException { | |
// handle custom exception type | |
rethrow; // 'rethrow' allows you to rethrow the error caught. | |
} on Exception catch(e) { | |
// Catch all other Exceptions | |
} catch(e) { | |
// Catch anything else | |
} finally { | |
// do this at the very end.. | |
} | |
// Uris | |
var uri = 'https://example.org/api?foo=some message'; | |
var encodedWholeUrlSafely = Uri.encodeFull(uri); | |
var encodedEverything = Uri.encodeComponent(uri); | |
var parsedUrl = Uri.parse('https://example.org:8080/foo/bar#frag') | |
print(parsed.scheme); | |
print(parsed.host); | |
print(parsed.path); | |
print(parsed.fragment); | |
print(parsed.origin); | |
// JSON | |
// import 'dart:convert' | |
var jsonString = ''' | |
[ | |
{"score": 40}, | |
{"score": 80} | |
] | |
'''; | |
var scores = jsonDecode(jsonString); | |
assert(scores is List); | |
assert(scores[0] is Map); | |
var jsonText = jsonEncode(scores); | |
} | |
// --------------- Class Tests ----------------- // | |
void classTests() { | |
// Default constructor | |
Person p1 = Person(); // Note: using 'new' is discouraged. | |
// Named constructors | |
Person p2 = Person.name("John"); | |
assert("John" == p2.getName()); | |
// None constructor | |
Person p3 = Person.none("John"); | |
assert(null == p3.getName()); | |
// All constructor | |
Person p4 = Person.all("John", 43); | |
// Initializer | |
var empWithInitializer = Employee.withInitializer({"age": "27", "name": "Dan", "id": "779"}); | |
} | |
// --------------- CLASSES ----------------- // | |
// Basic class | |
class Person { | |
// Properties | |
String name; | |
int age; | |
// Static Property | |
static const String FOO = "STATIC_PROP"; | |
// Constructors | |
Person(); // default constructor | |
Person.name(this.name); // named constructor. Assigns argument to this.name. | |
Person.none(String name : this(); // named constructor with argument that delegates to the default constructor. | |
Person.all(this.name, int age) { // named constructor with automatic assignment for one argument. | |
this.age = age; | |
} | |
Person.withAssert(this.name) : assert(name == "Foo"); // named constructor with assertion. | |
// Methods | |
int getAge() { | |
return age; | |
} | |
String getName() { | |
return name; | |
} | |
} | |
// Classes with Inheritance | |
class User { // Superclass | |
String name; | |
User(); | |
User.fromJson(Map json) { | |
name = json["name"] ?? "Guest"; | |
} | |
void doSomething() { | |
// do something... | |
} | |
} | |
class Employee extends User { // Subclass | |
String id; | |
String age; | |
// Note: constructors are not inherited so must call 'super' | |
Employee.fromJson(Map json) : super.fromJson(json) { | |
id = json["id"] ?? "-NO ID-"; | |
} | |
// Constructors can use initializers to assign variables. Seperated by commas. | |
Employee.withInitializer(Map json) : age = json["age"], id = json["id"] { | |
// other constructor setup... | |
} | |
@override // add annotation | |
void doSomething() { | |
super.doSomething(); // call the superclass if wanted | |
// do other stuff... | |
} | |
} | |
// Abstract Classes | |
abstract class MyAbstractClass { // the 'implementation' | |
void doSomething(); // must be implemented | |
} | |
class MyConcreteClass extends MyAbstractClass { // the 'concrete' class | |
void doSomething() { | |
// do actual implementation here... | |
} | |
} | |
// Implementation | |
class MyImpl { | |
final String name; | |
MyImpl(this.name); | |
} | |
class MyImplConcrete implements MyImpl { | |
get name => this.name; | |
} | |
// Generics | |
abstract class Cache<T> { | |
T getByKey(String key); | |
void setByKey(String key, T value); | |
// Generic Method: | |
// Note: having the 'first<T>' allows use in the return and arguments on line 1 and | |
// the local variable on line 2. | |
T first<T>(List<T> ts) { | |
T temp = ts[0]; | |
return temp; | |
} | |
} | |
// Overriding and Implementation | |
class OverrideExample implements Comparable<OverrideExample> { | |
final int length; | |
String firstName; | |
String lastName; | |
OverrideExample(this.length); | |
// Implement 'Comparable' and override 'compareTo' to use with > <. Ususually for sorting. | |
@override | |
int compareTo(OverrideExample other) => length - other.length; | |
// Override 'hashCode' for specifying unique instances | |
@override | |
int get hashCode { | |
int result = 17; | |
result = 37 * result + firstName.hashCode; | |
result = 37 * result + lastName.hashCode; | |
return result; | |
} | |
// Generally implement operator == if you override hashCode. | |
@override | |
bool operator ==(dynamic other) { | |
if (other is! OverrideExample) return false; | |
OverrideExample person = other; | |
return (person.firstName == firstName && person.lastName == lastName); | |
} | |
} | |
// --------------- OTHER ----------------- // | |
// Mixins | |
mixin PianoPlayer { | |
bool canPlayPiano = true; | |
void playSong() { | |
// play song... | |
} | |
} | |
// - use like this: | |
class Person with PianoPlayer {...} | |
// Enums | |
enum Colors { | |
red, | |
green, | |
blue | |
} | |
// Typedefs | |
// Useful for declaring types for functions | |
typedef Compare<T> = int Function(T a, T b); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment