This summary from dartlang.org for learning purpose

Function and Operators

Optional named parameters

When calling a function, you can specify named parameters using paramName: value . For example:

enableFlags(bold: true, hidden: false);

When defining a function, use {param1, param2, …} to specify named parameters:

/// Sets the [bold] and [hidden] flags ...

void enableFlags({bool bold, bool hidden}) {

// ...

}

~/ Divide, returning an integer result

assert(5 ~/ 2 == 2); // Result is an int

Cascade notation (..)

Cascades ( .. ) allow you to make a sequence of operations on the same object. In addition to function calls, you can also access fields on that same object. This often saves you the step of creating a temporary variable and allows you to write more fluid code.

querySelector('#confirm') // Get an object.

..text = 'Confirm' // Use its members.

..classes.add('important')

..onClick.listen((e) => window.alert('Confirmed!'));

expr1 ?? expr2

If expr1 is non-null, returns its value; otherwise, evaluates and returns the value of expr2.

Switch and case

Each non-empty case clause ends with a break statement, as a rule. Other valid ways to end a non-empty case clause are a continue, throw, or return statement.

var command = 'OPEN';

switch (command) {

case 'OPEN':

executeOpen();

// ERROR: Missing break



case 'CLOSED':

executeClosed();

break;

}

Classes

const constructor instead of new :

var p = const ImmutablePoint(2, 2);

Named constructors

Use a named constructor to implement multiple constructors for a class or to provide extra clarity:

class Point {

num x, y; Point(this.x, this.y); // Named constructor

Point.origin() {

x = 0;

y = 0;

}

}

Invoking a non-default superclass constructor

class Person {

String firstName; Person.fromJson(Map data) {

print('in Person');

}

} class Employee extends Person {

// Person does not have a default constructor;

// you must call super.fromJson(data).

Employee.fromJson(Map data) : super.fromJson(data) {

print('in Employee');

}

}

Initializer list

Besides invoking a superclass constructor, you can also initialize instance variables before the constructor body runs. Separate initializers with commas.

// Initializer list sets instance variables before

// the constructor body runs.

Point.fromJson(Map<String, num> json)

: x = json['x'],

y = json['y'] {

print('In Point.fromJson(): ($x, $y)');

}

Redirecting constructors

Sometimes a constructor’s only purpose is to redirect to another constructor in the same class. A redirecting constructor’s body is empty, with the constructor call appearing after a colon (:).

class Point {

num x, y; // The main constructor for this class.

Point(this.x, this.y); // Delegates to the main constructor.

Point.alongXAxis(num x) : this(x, 0);

}

Constant constructors

If your class produces objects that never change, you can make these objects compile-time constants. To do this, define a const constructor and make sure that all instance variables are final .

class ImmutablePoint {

static final ImmutablePoint origin =

const ImmutablePoint(0, 0); final num x, y; const ImmutablePoint(this.x, this.y);

}

Factory constructors

// singleton pattern

Use the factory keyword when implementing a constructor that doesn’t always create a new instance of its class. For example, a factory constructor might return an instance from a cache, or it might return an instance of a subtype.

The following example demonstrates a factory constructor returning objects from a cache:

class Logger {

final String name;

bool mute = false; // _cache is library-private, thanks to

// the _ in front of its name.

static final Map<String, Logger> _cache =

<String, Logger>{}; factory Logger(String name) {

if (_cache.containsKey(name)) {

return _cache[name];

} else {

final logger = new Logger._internal(name);

_cache[name] = logger;

return logger;

}

} Logger._internal(this.name); void log(String msg) {

if (!mute) print(msg);

}

}

Overridable operators

https://www.dartlang.org/guides/language/language-tour#overridable-operators

mixins

https://www.dartlang.org/articles/language/mixins

Libraries and visibility

Importing only part of a library

If you want to use only part of a library, you can selectively import the library. For example:

// Import only foo.

import 'package:lib1/lib1.dart' show foo; // Import all names EXCEPT foo.

import 'package:lib2/lib2.dart' hide foo;

Lazily loading a library

To lazily load a library, you must first import it using deferred as .

import 'package:greetings/hello.dart' deferred as hello;

When you need the library, invoke loadLibrary() using the library’s identifier.

Future greet() async {

await hello.loadLibrary();

hello.printGreeting();

}

Callable classes

To allow your Dart class to be called like a function, implement the call() method.