本文更新於2024-12-22,使用Dart 2.18.2。
目錄
- 關鍵字
- 常量
- 變量
- 基本數據類型
- 數值
- 字符串
- 布爾
- 列表
- 集合
- 映射
- 運算符
- 運算符優先級
- 算數運算符
- 關係運算符
- 類型判定運算符
- 賦值運算符
- 邏輯運算符
- 位運算符
- 條件運算符
- 訪問運算符
- 流程控制
- 條件語句
- if-else
- switch-case
- 循環語句
- for
- for-in
- while
- do-while
- break語句
- continue語句
- 條件語句
- 斷言
- 異常
- 函數
- 箭頭函數
- 可選位置參數
- 可選命名參數
- 閉包
- 主函數
- 類
- 成員變量/實例變量
- getter和setter
- 靜態變量/類變量
- 構造函數
- 默認無參構造函數
- 顯式聲明構造函數
- 命名構造函數
- 構造函數簡寫
- 初始化列表
- 重定向構造函數
- 常量構造函數
- 工廠方法的構造函數
- 自動調用父類無參構造函數
- 顯式調用父類構造函數
- 成員方法/實例方法
- 靜態方法/類方法
- 繼承
- 函數重寫
- 運算符重寫
- 抽象類與抽象方法
- 接口
- Mixin特性
- 可調用的類
- 成員變量/實例變量
- 枚舉
- 類型定義
- 泛型
- 函數泛型
- 類泛型
- 異步
- 在循環中異步
- 註解/元數據
- @deprecated
- @override
- @proxy
- 註釋
- 單行註釋
- 多行註釋
- 文檔註釋
- 庫
- import內置庫
- import包庫
- import本地庫
- import-as
- import-show
- import-hide
- import-deferred as懶加載
- 包
可以使用dart run FILENAME運行程序文件。
關鍵字
- abstract
- as
- assert
- async
- await
- break
- case
- catch
- class
- const
- continue
- covariant
- default
- deferred
- do
- dynamic
- else
- enum
- export
- extends
- external
- factory
- false
- final
- finally
- for
- get
- hide
- if
- implements
- import
- in
- interface
- is
- library
- mixin
- new
- null
- on
- operator
- part
- rethrow
- return
- set
- show
- static
- super
- switch
- sync
- this
- throw
- true
- try
- typedef
- var
- void
- while
- with
- yield
常量
const聲明的是編譯時常量。
cosnt s1 = "";
const String s2 = "";
final s3 = "";
final String s4 = "";
var list = const[1, 2, 3];
const list = [1, 2, 3];
var dog = const Dog();
const dog = Dog();
變量
var a1;
var a2 = null;
dynamic a3;
dynamic a4 = "";
var s1 = "";
String s2 = "";
基本數據類型
數值
- int: 64位。範圍為[-2^63 ~ 263-1]。編譯為JavaScript時使用JavaScript的範圍[-253 ~ 2^53-1]。
- double:64位。範圍約為[-1.7E308 ~ 1.7E308]。
字符串
使用UTF-16編碼。
var s1 = '\'';
var s2 = "\"";
var s3 = '''1
2''';
var s4 = """1
2""";
var s5 = "\u2665\u{1f47b}";
var a1 = '$s1 ${s2}';
var a2 = "$s1 ${s2}";
var a3 = s1 + " " + s2;
var a4 = s1 * 3;
var a5 = "${s1+s2}";
布爾
var b1 = true;
bool b2 = false;
列表
var l = [1, "2", 1];
集合
var s = {1, "2"};
映射
var m1 = {};
var m2 = {
"a": 1,
"b": "2"
};
運算符
運算符優先級
從高到低依次為:
| 描述 | 運算符 |
|---|---|
| 一元后綴 | ++,--,(),[],.,?. |
| 一元前綴 | -,!,~,++,-- |
| 乘除 | *,/,~/,% |
| 加減 | +,- |
| 移位 | <<,>>,>>> |
| 按位與 | & |
| 按位異或 | ^ |
| 按位或 | | |
| 關係和類型測試 | >=,>,<=,<,as,is,is! |
| 相等判斷 | ==,!= |
| 邏輯與 | && |
| 邏輯或 | || |
| 為空判斷 | ?? |
| 條件 | ? : |
| 級聯 | .. |
| 賦值 | =,+=,-=,*=,/=,~/=,%=,<<=,>>=,>>>=,&=,^=,|= |
算數運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| + | 1 + 2 | 相加 |
| - | 1 - 2 | 相減 |
| - | -1 | 負數 |
| * | 1 * 2 | 相乘 |
| / | 1 / 2 | 相除(返回浮點數) |
| ~/ | 1 ~/ 2 | 相除(返回整數) |
| % | 1 % 2 | 取餘 |
| ++ | ++n | (前)自增 |
| ++ | n++ | (後)自增 |
| -- | --n | (前)自減 |
| -- | n-- | (後)自減 |
關係運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| == | 1 == 2 | 相等 |
| != | 1 != 2 | 不等 |
| > | 1 > 2 | 大於 |
| >= | 1 >= 2 | 大於等於 |
| < | 1 < 2 | 小於 |
| <= | 1 <= 2 | 小於等於 |
類型判定運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| as | 1 as int | 類型轉換(結果為運算符後的類型) |
| is | 1 is int | 是此類型(結果為bool類型) |
| is! | 1 is! int | 非此類型(結果為bool類型) |
賦值運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| = | n = 2 | 賦值 |
| += | n += 2 | 即 n = n + 2 |
| -= | n -= 2 | 即 n = n - 2 |
| *= | n *= 2 | 即 n = n * 2 |
| /= | n /= 2 | 即 n = n / 2 |
| ~/= | n ~/= 2 | 即 n = n ~/ 2 |
| %= | n %= 2 | 即 n = n % 2 |
| <<= | n <<= 2 | 即 n = n << 2 |
| >>= | n >>= 2 | 即 n = n >> 2 |
| >>>= | n >>>= 2 | 即 n = n >>> 2 |
| &= | n &= 2 | 即 n = n & 2 |
| |= | n |= 2 | 即 n = n | 2 |
| ^= | n ^= 2 | 即 n = n ^ 2 |
邏輯運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| ! | !true | 非 |
| || | true || false | 或 |
| && | true && false | 與 |
位運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| & | 1 & 2 | 按位與 |
| | | 1 | 2 | 按位或 |
| ^ | 1 ^ 2 | 按位異或 |
| ~ | ~1 | 按位取反(結果為相反數減一) |
| << | 1 << 2 | 按位左移 |
| >> | 1 >> 2 | 有符號按位右移(左側填充符號位) |
| >>> | 1 >>> 2 | 無符號按位右移(左側填充0) |
條件運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| ? : | v ? t : f | 條件判斷(如v為true取值t,否則取值f) |
| ?? | v ?? n | 非空判斷(如v非null取值v,否則取值n) |
訪問運算符
| 運算符 | 用法 | 描述 |
|---|---|---|
| () | f() | 函數調用 |
| [] | a[1] | 使用索引訪問元素 |
| . | a.b | 訪問對象成員 |
| ?. | a?.b | 條件訪問對象成員(如a非null取值b,否則取值null) |
| .. | v..f1()..f2() | 級聯運算(等價於v.f1();v.f2(),嚴格意義上並不是一個運算符,只是一個特殊語法) |
流程控制
條件語句
if-else
if (condition1) {
} else if (condition2) {
} else {
}
switch-case
switch (v) {
case 1:
case 2:
print("");
break;
default:
}
循環語句
for
for (var i = 0; i < n; i++) {
}
for-in
for (var v in set) {
}
while
while (condition) {
}
do-while
do {
} while(condition);
break語句
switch (v) {
case 1:
case 2:
print("");
break;
default:
}
for (var i = 0; i < n; i++) {
break;
print(i);
}
continue語句
for (var i = 0; i < n; i++) {
if (i == 0) {
continue;
}
print(i);
}
斷言
斷言只在開發(Checked)模式下有效,在生產(Production)模式下無效。
assert(flag);
異常
try {
throw new Exception();
} on RangeError {
rethrow;
} catch (e) {
} finally {
}
函數
String join(String a, String b) {
return a + b;
}
add(a, b) {
return a + b;
}
run() {
}
var s = join("a", "b");
var n = add(1, 2);
var a = run();
箭頭函數
String join(String a, String b) => a + b;
可選位置參數
String join(String a, String b, [String c = "", String d = ""]) {
return a + b + c + d;
}
var s = join("a", "b", "c");
可選命名參數
String join(String a, String b, {String c: "", d: ""}) {
return a + b + c + d;
}
var s = join("a", "b", c: "c");
閉包
Function hello(String name) {
var say = () {
print("Hello $name");
};
return say;
}
var say = hello("Tom");
say();
主函數
void main(List<String> args) {
}
類
成員變量/實例變量
class Person {
String name = "";
int age = 0;
}
getter和setter
會為每個成員變量自動生成getter方法,對於非final修飾的成員變量也會自動生成setter方法。
class Person {
String name = "";
String get Name {
return name;
}
set Name(String n) {
name = n;
}
}
var p = new Person();
p.Name = "Tom";
print(p.Name);
靜態變量/類變量
class Person {
String name = "";
int age = 0;
static int total = 1000;
static Person me = new Person();
}
print(Person.total);
構造函數
構造函數的執行順序為:實例變量賦值 -> 初始化參數列表 -> 父類構造函數 -> 本類構造函數。
默認無參構造函數
class Person {
String name = "";
int age = 0;
}
var p1 = new Person();
var p2 = Person();
默認自動生成無參構造函數:
Person() {
}
顯式聲明構造函數
class Person {
String name = "";
int age = 0;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
var p = new Person("Tom", 10);
命名構造函數
class Person {
String name = "";
int age = 0;
Person.myself(age) {
name = "Tom";
this.age = age;
}
}
var p = new Person.myself(10);
構造函數簡寫
class Person {
String name = "";
int age = 0;
Person(this.name, this.age);
Person.create(this.name, {this.age: 0});
}
class Student extends Person {
String number = "";
Student(super.name, super.age);
}
var p1 = new Person("Tom", 10);
var p2 = new Person.create("Tom", age: 10);
var s = new Student("Tom", 10);
初始化列表
class Person {
String name = "";
int age = 0;
Person.myself(int age): name = "Tom", this.age = age {
}
}
var p = new Person.myself(10);
重定向構造函數
class Person {
String name = "";
int age = 0;
Person(this.name, this.age);
Person.myself(int age): this("Tom", age);
}
var p = new Person.myself(10);
常量構造函數
class Person {
final String name;
final int age;
const Person(this.name, this.age);
}
var p1 = new Person("Tom", 10);
var p2 = const Person("Tom", 10);
工廠方法的構造函數
class Person {
String name = "";
int age = 0;
static Map<String, Person> _people = {};
Person(this.name, this.age);
factory Person.Tom() {
var name = "Tom";
var p = _people[name];
if (p == null) {
p = Person(name, 0);
_people[name] = p;
}
return p;
}
}
var p = new Person.Tom();
自動調用父類無參構造函數
class Person {
String name = "";
int age = 0;
}
class Student extends Person {
String number = "";
}
var s = new Student();
顯式調用父類構造函數
class Person {
String name = "";
int age = 0;
Person(this.name, age);
Person.myself(int age) {
name = "Tom";
this.age = age;
}
}
class Student extends Person {
String number = "";
Student(String name, int age, String number): super(name, age) {
this.number = number;
}
Student.myself(int age, String number): this.number = number, super.myself(age) {
}
}
var s1 = new Student("Tom", 10, "no.1");
var s2 = new Student.myself(10);
成員方法/實例方法
class Person {
String name = "";
int age = 0;
String info() {
return "Person name is $name and age is $age.";
}
}
var s = new Student();
s.info();
靜態方法/類方法
class Person {
String name = "";
int age = 0;
static readme() {
print("Person!");
}
}
Person.readme();
繼承
不支持多繼承。
class Person {
String name = "";
int age = 0;
String info() {
return "Person name is $name and age is $age.";
}
}
class Student extends Person {
String number = "";
}
var s = new Student();
s.info();
函數重寫
class Person {
String name = "";
int age = 0;
String info() {
return "Person name is $name and age is $age.";
}
}
class Student extends Person {
String number = "";
@override
String info() {
return super.info() + " Student number is $number.";
}
}
運算符重寫
class Person {
String name = "";
int age = 0;
Person(this.name, this.age);
Person operator +(Person p) {
var name = this.name + " and " + p.name;
var age = this.age + p.age;
return new Person(name, age);
}
}
var p1 = new Person("Tom", 10);
var p2 = new Person("Jerry", 9);
var p = p1 + p2;
可重寫的運算符有:
- <
- <=
-
=
- ==
-
-
-
- /
- ~/
- %
- &
- |
- ^
- ~
- <<
-
- []
- []=
抽象類與抽象方法
抽象類無法被實例化。
abstract class Person {
String name = "";
int age = 0;
String info();
}
class Student extends Person {
String number = "";
@override
String info() {
return "Person name is $name and age is $age. Student number is $number.";
}
}
接口
class Person {
String name = "";
int age = 0;
}
abstract class Say {
int voice = 0;
void say();
}
class Hello {
void hello() {
print("hello!");
}
}
class Student extends Person implements Say, Hello {
String number = "";
@override
int voice = 0;
@override
void say() {
print("Person name is $name and age is $age. Student number is $number.");
}
@override
void hello() {
print("hello!");
say();
}
}
Mixin特性
class Person {
String name = "";
int age = 0;
}
class Run {
void run() {
print("run!");
}
}
abstract class Say {
void say();
}
class Student extends Person with Run implements Say {
String number = "";
@override
void say() {
print("Person name is $name and age is $age. Student number is $number.");
}
}
var s = new Student();
s.run();
可調用的類
class Run {
call() {
print("run");
}
}
class Say {
call(String a, String b) {
print("say $a $b");
}
}
var run = new Run();
run();
var say = new Say();
say("a", "b");
枚舉
無法繼承,無法使用Mixin特性,無法實例化。
enum Grade {
grade1,
grade2
}
var grade = Grade.grade1;
var index = Grade.grade1.index;
類型定義
typedef Repeat = String Function(String str);
typedef Name = String;
Name name = "Tom";
Repeat f = (str) {
return str + ", " + str;
};
var s = f(name);
泛型
函數泛型
String add<T>(T a, T b) {
return a.toString() + b.toString();
}
String addString<T extends String>(T a, T b) {
return a + b;
}
add(1, 2);
addString("a", "b");
類泛型
class Add<T> {
String add(T a, T b) {
return a.toString() + b.toString();
}
}
class AddString<T extends String> {
String add(T a, T b) {
return a + b;
}
}
new Add().add(1, 2);
new AddString().add("a", "b");
異步
異步本質上是使用isolates運行模式進行併發。
void main(List<String> args) {
work();
print(2);
}
work() async {
print(1);
var str = await takeTime();
print(4);
print(str);
}
Future<String> takeTime() async {
var str = await new Future.delayed(new Duration(seconds: 2), () {
print("...");
print(3);
return "hello";
});
return str;
}
在循環中異步
void main(List<String> args) async {
Stream<String> stream = Stream.fromFuture(new Future.delayed(new Duration(seconds: 2), () {
print("...");
print(2);
return "hello";
}));
print(1);
await for (var str in stream) {
print(str);
}
print(3);
}
註解/元數據
@deprecated
棄用。
@deprecated
// Should use Hello();
void hello() {
}
@override
重寫。
class Person {
String name = "";
}
class Student extends Person {
@override
String name = "";
}
@proxy
註釋
單行註釋
// Comment.
多行註釋
/*
Comment.
Comment.
Comment.
*/
/* Comment.
Comment.
Comment. */
文檔註釋
/**
* This is a demo.
*
* Refer [say] for detail.
*/
void hello() {
}
/// This is a demo.
/// Used by [hello].
void say() {
}
庫
標識符除非以“_”開頭,否則都是對庫外可見的。
import內置庫
import 'dart:math';
void main(List<String> args) {
print(pi);
}
import包庫
import 'package:flutter/material.dart';
import本地庫
lib.dart:
var _name = "lib.dart";
class Hello {
void hello() {
print("hello " + _name);
}
}
main.dart:
import 'lib.dart';
void main(List<String> args) {
new Hello().hello();
}
import-as
src/liba.dart:
class Hello {
void helloA() {
print("hello a");
}
}
src/libb.dart:
class Hello {
void helloB() {
print("hello b");
}
}
main.dart:
import 'src/liba.dart' as liba;
import 'src/libb.dart' as libb;
void main(List<String> args) {
new liba.Hello().helloA();
new libb.Hello().helloB();
}
import-show
lib.dart:
class Hello {
}
class Say {
}
class Run {
}
main.dart:
import 'lib.dart' show Hello, Say;
void main(List<String> args) {
new Hello();
new Say();
}
import-hide
lib.dart:
class Hello {
}
class Say {
}
class Run {
}
main.dart:
import 'lib.dart' hide Run;
void main(List<String> args) {
new Hello();
new Say();
}
import-deferred as懶加載
lib.dart:
class Hello {
hello() {
print("hello");
}
}
main.dart:
import 'lib.dart' deferred as lib;
void main(List<String> args) {
print("main");
hello();
}
void hello() async {
await lib.loadLibrary();
new lib.Hello().hello();
}
包
包目錄結構如下:
- lib/:源代碼目錄。
- src/:私有源代碼目錄。
- pubspec.yaml:配置文件。
flutter包的material.dart:
export 'src/material/app.dart';
main.dart:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo'
);
}
}