Jim Cheung

reading notes on

Dart Up and Running

Chapter 1, Quick Start

(no notes)

Chapter 2, A Tour of the Dart Language

Important Concepts

Variables

Variables are references.

Uninitialized variables have an initial value of null.

int lineCount;
assert(lineCount == null);

the assert() call is ignored in production mode.

you have the option of adding static types to your variable declarations:

String name = 'Bob';

for local variables, use var, more details check Dart Style Guide

if you never intend to change a variable, use final or const, either instead of var or in addition to a type:

final name = 'Bob';
// or
final String name = 'Bob';

a local, top-level, or class variable that's declared as final is initialized the first time it's used. lazy initialization of final variables helps apps start up faster.

Built-in Types

Dart has special support for the following types:

you can initialize an object of any of above using a literal (you can also use constructors to do it)

Numbers

Dart numbers come in two flavors:

Both of them are subtypes of num.

if number inclues a decimal, it's a double.

var x = 1; // int
var y = 1.1; // double
var one = int.parse('1'); // String -> int
var onePointOne = double.parse('1.1'); // String -> double
String oneAsString = 1.toString(); // int -> String
String piAsString = 3.14159.toStringAsFixed(2); // '3.14', double -> String

Strings

A Dart string is a sequence of UTF-16 code units. you can use either single or double quotes.

You can put the value of an expression inside a string by using ${expression}. if the expression is an identifier, you can skip the {}.

use == tests whether two objects are equivalent. two strings are equivalent if they have the same characters.

you can concatenate string using adjacent string literials:

var s = 'String ''concatenation'
        " works even over line breaks.";

Another way to create a multi-line string: use a triple quote with either single or double quotation marks:

var s1 = '''
You can create
multi-line stirngs like this one
''';

you can create a raw string by prefix it with r:

var s = r"In a raw string, even \n isn't special.";

Booleans

Dart has a type named bool. only two objects have type bool: the boolean literals, true and false.

when Dart expects a boolean value, only the value true is treaded as true. all other values are treated as false.

var name = 'Bob';
if (name) {
    print('You have a name'); // Prints in JavaScript, not in Dart
}

run dart in checked mode to throw these kind of exceptions.

you should explicitly check for values:

// check empty string
assert(foo.isEmpty());
// check for zero
assert(foo <= 0);
// check for null
assert(foo == null);
// check for NaN
assert(foo.isNan());

Lists

Dart list literals look like JavaScript array literials:

var list = [1,2,3];

List type is a sub-type of Collection

Maps

a map is an object that associates keys and values.

var gifts = {
    'first': 'partridge',
    'second': 'turtledoves'
};

in map literials, each key must be a string. if you use a Map constructor, any object can be a key.

a map value can be any object, including null.

if you look for a key that isn't in a map, you get a null in return:

assert(gifts['fifth'] == null);

Functions

exmaple of a function:

void printNumber(num number) {
    print('The number is $number.');
}
// omitting types is ok
printNumber(number) {
    print('The number is $number.');
}

in function that contains just one expression, you can use a shorthand syntax:

printNumber(number) => print('The number is $number.');

the => expr; syntax is a shorthand for { return expr;}.

only an expression - not a statement - can appear between => and ;

a function can have two types of parameters: required or optional. required parameters are listed first, followed by any optional parameters.

optional parameters can be either positional or named, but not both.

both kinds can have default values. the default value must be compile-time constants such as literals.

if you need to know whether the caller passed in a value for an optional parameter, use the syntax ?param:

if (?device) {
    // ...
}

optional named parameters

when calling a function, you can specify named parameters using paramName: value:

enableFlags(bold: true, hidden: false);

when defining a function, use {param1, param2, ...} to specify named parameters:

enableFlags({bool bold, bool hidden}) {
    // ... 
}
// use : to specify default values
enableFlags({bool bold: false, bool hidden: false}) {
    // ... 
}

optional positional parameters

wrapping a set of function parameters in [] marks them as optional positional parameters:

String say(String from, String msg, [String device]) {
    var result = '$from says $msg';
    if (device != null) {
        result = '$result with a $device';
    }
    return result;
}
// use = to specify default values
String say(String from, String msg, [String device='carrier pigeon', String mood]) {
    ...
}

Functions as first-class objects

you can pass a function as a paramter to another function:

printElement(element) {
    print(element);
}
var list = [1,2,3];
list.forEach(printElement);

you can assign a function to a variable:

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';

Lexical closures

functions can close over variables defined in surrounding scopes.

Return Values

All functions return a value. (null if not specified)

Equality and Relational Operators

how == operator works:

  1. if x or y is null, return true if both are null, and false if only one is null
  2. return the result of the method invocation x.==(y)

Type Test Operators

if (person is Person) { // type check
    person.firstName = 'Bob';
}
// shorter version
(person as Person).firstName = 'Bob';

use the as operator to case an object to a particular type.

Control Flow Statements

Closures inside of Dart's for loops capture the value of the index, avoiding a common pitfall found in JavaScript:

var callbacks = [];
for (var i = 0; i < 2; i++) {
    callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
// 0 then 1 in dart
// 2 then 2 in javascript

If the object is a Collection, you can use forEach

using forEach is a good option if you don't need to know the current iteration counter.

candidates.forEach((candidate) => candidate.view());

Collections also support the for-in form of iteration:

var collection = [0, 1 2];
for (var x in collection) {
    print(x);
}

Break and Continue

use break to stop looping

while(true) {
    if (shutDownRequested()) break;
    processIncomingRequests();
}

use continue to skip to the next loop iteration:

for (int i = 0; i < candidates.length; i++) {
    var candidate = candidates[i];
    if (candidate.yearsExperience < 5) {
        continue;
    }
    candidate.interview();
}
// shorter version if using Collection
candidates.filter((c) => c.yearsExperience >= 5)
        .forEach((c) => c.interview());

Switch and Case

switch in dart using == for comparison.

each non-empty case clause ends with a break statement, other valid ways to end it are countinue, throw, or return

use continue and label:

switch(command) {
    case 'CLOSED':
        executeClosed();
        continue nowClosed; // to nowClosed label
nowClosed:
    case 'NOW_CLOSED':
        // runs for both CLOSED and NOW_CLOSED
        executeNowClosed();
        break;
}

A case clause can have local variables, which are visible only inside the scope of that clause.

Assert

Assert statements work only in checked mode, have no effect in production mode.

when assertion fails, AssertionError exception is thrown.

Exceptions

if the exception isn't caught, the isolate that raised the exception is suspended, and typically the isolate and its program are termincated.

all of dart's exceptions are unchecked exceptions.

dart provides Exception and Error types. however, cart program can throw any non-null object - not just Exception and Error objects - as an exception.

Throw

throw new ExpectException("...");
// or throw arbirary objects.
throw '...';

throwing an exception is an expression, you can throw exceptions in => statements:

String get prettyVersion() => throw const NotImplementedException();

Catch and Finally

try {
    breedMoreLlamas();
} on OutOfLlamasException { // a specific exception
    buyMoreLlamas();
} on Exception catch(e) { // anything else that is an exception
    print('Unknown exception: $e');
} catch(e) { // no specified type, handles all
    print('Something really unknown: $e');
} finally {
    cleanLlamaStalls();
}

you can use either on or catch or both.

use on when you need to specify the exception type. use catch when your exception handler needs the exception object.

Classes

Chapter 3, A Tour of the Dart Libraries

dart:core - Numbers, Collections, Strings, and More dart:async - Asynchronous Programming dart:math - Math and Random dart:html - Browser-Based Apps dart:io - I/O for Command-Line Apps dart:convert - Decoding and Encoding JSON, UTF-8, and More dart:mirrors - Reflection

Chapter 4, Tools

pub: The Dart Package Manager Dart Editor Dartium: Chromium with the Dart VM dart2js: The Dart-to-JavaScript Compiler dart: The Standalone VM dartanalyzer: The Static Analyzer

Chapter 5, Walkthrough: Dart Chat

How to Run Dartiverse Search How Dartiverse Search Works The Client's HTML Code The Client's Dart Code The Server's Code What Next?