基本數據類型
Number
-
int
- int a = 1;
- int b = 0xDEFFFF;
-
double
- double x = 1.0;
-
轉換
- var a = int.parse('1');
- var b = double.parse('2.5');
- 指定進制:
var hex = int.parse('10', radix: 16); - String a = 1.toString();
- String b = 3.1415.toStringFixed(2);
b = '3.14'
String
- var a = 'this is a string text';
- var b = '''
this is a multiple line string
text....
''';
Boolean
- bool a = true;
- bool b = 1 > 0;
List
- var a = [1, 2, 3];
- List<String> = ['a', 'b'];
- [1,2,3].sort((a,b) => a.compareTo(b));
Set
- var a = {'a', 'b'};
- .length
- .add()
- .addAll(aSet)
Map
- var aMap = Map();
- var aMap = {};
- Map<String, dynamic> map = {
'a': 1,
'b': 'hello',
'c': ()=>print('hello')
};
map.forEach((key, val){
print('val');
}); - Map<int, String> b = {0: 'a', 1: 'b'};
Rune
- UTF-32編碼字符
- (?) 是 \u2665
- (?) 是 \u{1f600} -- 非4個字符的用{}包裹
函數
Function類
- int aFunc(int a, int b) => a+b;
- void aFunc(){}
- aFunc(){}
- 用{}指定命名參數
aFunc(title: String, {Key key, @required Widget child}) - 用[]指定可選參數
aFunc(title: String, {Key key, @required Widget child}) - 設置默認參數值
aFunc(title: 'hello', {Key key, @required Widget child}) - 匿名函數(lambda/closure):(){}
- 函數返回類型
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
運算符
算數
- ~/
除數取整:5 ~/ 2 = 2 - %
除數取余:5 % 2 = 1
類型判定
- as:將對象強制轉換為特定類型
(emp as Person).firstName = 'Bob'; - is:判定對象是否是指定的類型
obj is Object;
is!:是上面的取反
賦值運算符
- ??=
b ??= 'a'; (如果b為null,則b='a',否則不變)
條件表達式
- ? :
a = b>0 ? 'yes' : 'no'; - ??
a = b ?? 'a'; (如果b為null,則a='a',否則a=b)
級聯運算符
- .. :對同一個對像進行一系列的操作
querySelector('#confirm') // 獲取對象。
..text = 'Confirm' // 調用成員變量。
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
上面代碼等同于:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
- 嚴格的來講, “兩個點” 的級聯語法不是一個運算符。 它只是一個 Dart 的特殊語法。
可選類型(類似swift的Optional)
- ?.
a = obj?.name; (如果obj為null,則a=null;
如果obj.name為null,a=null)
控制流程語句
if-else
for
for(var i=0; i<5; i++){}
-
forEach
- [1,2,3].forEach((val) => print('val: $val'));
-
for-in
- (for var i in [1,2,3]){}
switch-case
- var word = 'a';
switch(word){
case 'b':
print('hello b');
break;
default: break;
}
assert
- assert(text != null);
- assert 語句只在開發環境中有效, 在生產環境是無效的;
枚舉
enum Color {
red, green, blue
}
Color.red.index == 0;
Color.values[0] == Color.red;
異常
try-catch
- try{
doingSomething();
} on Exception catch(e) {
print('明確類型的異常');
} catch(e, s){
print('不明確的異常:s');
}
rethrow
finally
- try{
} finally {
} - try{
} catch(e) {
} finally {
}
類
Dart 是一種基于類和 mixin 繼承機制的面向對象的語言。
繼承用extends關鍵字;
實現多個接口(抽象類)用implements關鍵字;
重寫父類方法用@override關鍵字;
獲取對象的類型
- Type aType = a.runtimeType;
實例變量
- class Point {
int x; // 聲明實例變量 x,初始值為 null 。
int y; // 聲明實例變量 y,初始值為 null 。
double z = 0; // 聲明示例變量 z,初始值為 0 。
} - 所有未初始化的實例變量默認值都為 “null” ,而不是int的為0
- 隱式生成setter和getter方法
構造函數
-
默認構造函數
- var p = Person();
var p = new Person(); (new是可選的)
- var p = Person();
-
自定義構造函數
- Person(int age, String name){
this.age = age;
this.name = name;
}
this指代當前實例對象,跟oc中的self一樣。
上面的代碼等同于:
Person(this.age, this.name);
- Person(int age, String name){
- 子類不會繼承父類的構造函數。 子類不聲明構造函數,那么它就只有默認構造函數 (匿名,沒有參數)。
- 如果希望使用父類中定義的命名構造函數創建子類, 就必須在子類中實現該構造函數。
- 默認情況下,子類的構造函數會自動調用父類的默認構造函數
-
命名構造函數
- 指定意圖的構造函數:
Point.origin() {
x = 0;
y = 0;
}
- 指定意圖的構造函數:
-
父類構造函數
- class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
} - class 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');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
- // 在構造函數體執行之前,
// 通過初始列表設置實例變量。
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): (y)');
}
-
工廠構造函數
- 一個工廠構造函數可能會返回一個 cache 中的實例, 或者可能返回一個子類的實例。
- class Logger {
final String name;
bool mute = false;
// 從命名的 _ 可以知,
// _cache 是私有屬性。
static final Map<String, Logger> _cache =
<String, Logger>{};factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
} -
getters & setter
- class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// 定義兩個計算屬性: right 和 bottom。
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
} - class Rectangle {
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
-
抽象類
- 抽象方法只存在于 抽象類 中。
- abstract class Doer {
// 定義實例變量和方法 ...
void doSomething(); // 定義一個抽象方法。
}
class EffectiveDoer extends Doer {
void doSomething() {
// 提供方法實現,所以這里的方法就不是抽象方法了...
}
}
-
noSuchMethod()
- 這樣可以避免一些dynamic類型的實例對象類型錯誤,導致訪問某些方法時崩潰問題;
如Person a = null; a.name(崩潰); - class A {
// 如果不重寫 noSuchMethod,訪問
// 不存在的實例變量時會導致 NoSuchMethodError 錯誤。
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
- 這樣可以避免一些dynamic類型的實例對象類型錯誤,導致訪問某些方法時崩潰問題;
-
Mixin
- 為類添加功能
用with關鍵詞,類似于swift的協議 - class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
} - mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}- 指定類型的mixin
mixin MusicalPerformer on Musician {
// ···
}
- 為類添加功能
-
靜態方法/類方法
- class Point {
num x, y;
Point(this.x, this.y);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
} - class Point {
-
靜態常量
- class Queue {
static const initialCapacity = 16;
// ···
}
- class Queue {
泛型
<T>表示
List<String> list = ['a', 'b'];
var list = <int>[0, 1, 2];
var map = <String, dynamic>{};
限制泛型類型
- class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}
泛型函數
- T aFunc<T>(T param){
}
庫
import
- import 'dart:html';
import 'package:test/test.dart'; - 前綴
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// 使用 lib1 中的 Element。
Element element1 = Element();
// 使用 lib2 中的 Element。
lib2.Element element2 = lib2.Element();
- 導入一部分
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
- 延遲加載:讓應用在需要的時候再加載庫
import 'package:greetings/hello.dart' deferred as hello;
當需要使用的時候,使用庫標識符調用 loadLibrary() 函數來加載庫:
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
在一個庫上你可以多次調用 loadLibrary() 函數。但是該庫只是載入一次。
export
library
part
異步
返回Future/Stream
async-await關鍵字
- Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
} - await 表達式會阻塞代碼的執行,直到需要的對象返回為止。
Isolates
所有 Dart 代碼都在隔離區( isolates )內運行,而不是線程。
每個隔離區都有自己的內存堆,確保每個隔離區的狀態都不會被其他隔離區訪問。
typedef
自定義函數類型
typedef NetworkRequestCompletion = void Function(Error error, Map<String, dynamic> json);
元數據
元數據注釋以字符 @ 開頭
/// Deprecated: Use [turnOn] instead.
@deprecated
void activate() {
turnOn();
}