Wiki
Dart語言教程
約 7 分鐘閱讀
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
1.程式碼規範
幾乎和C/C++一模一樣.
- 副檔名: dart語言檔案字尾以
.dart結尾 - 入口:dart檔案的入口方法為main方法
- 分號:dart檔案中絕大部分語句都需要加分號結尾,像
{ }後通常不加分號
2.Dart的變數
該節與C/C++高度相似.
2.1.字串型別-String
與C/C++中的std::string基本類似.
基礎用法:
- 關鍵字:String
- 語法:
String 属性名 = ‘文本内容’; - 特點:引號支援雙引號或者單引號,支援拼接及模板字串
進階用法:
- 語法:
String 属性名 = ‘文本内容$变量名’;或String 变量名 = ‘文本内容${变量名}’; - 注意:當存在模板中的內容是一個表示式的時候需要使用
${}, 不管是表示式還是變數,都更推薦使用${},儘量不要用$变量名了.
void main()
{
String name = 'Alice';
print(name); // Output: Alice
name = 'Bob';
print(name); // Output: Bob
String greeting = 'Hello, ${name}?$name!';
print(greeting); // Output: Hello, Bob?Bob!
String when = 'it is ${DateTime.now()},now';
print(when); // Output: it is 2026-02-16 14:46:17.818262,now
}
2.2.數字型別-int/double/num
與C/C++中的int,double基本類似.
基礎語法
- 場景:當我們需要描述一個數字型別的時候,需要使用int/num/double
- 區別:int-整型數字,double-小數 , num-可整型可小數
- 語法:
int/num/double 属性名 = 数值;
void main()
{
int age = 23;
print(age); // Output: 23
age = 24;
print(age); // Output: 24
double height = 1.78;
print(height); // Output: 1.78
height = 1.80;
print(height); // Output: 1.8
num weight = 90.5;
print(weight); // Output: 90.5
weight = 76;
print(weight); // Output: 76
}
三者本質區別:
num
├── int
└── double
- 👉 num 是父類
- 👉 int 和 double 是子類
直接賦值規則總表:
| 賦值方向 | 是否可以直接賦值 | 說明 |
|---|---|---|
| int → num | ✅ 可以 | 子類給父類 |
| double → num | ✅ 可以 | 子類給父類 |
| num → int | ❌ 不行 | 可能是 double |
| num → double | ❌ 不行 | 可能是 int |
| int → double | ❌ 不行 | Dart 不自動轉 |
| double → int | ❌ 不行 | 會丟失小數 |
| int → int | ✅ | |
| double → double | ✅ | |
| num → num | ✅ |
雖然無法直接賦值,但是可以轉化後再賦值.可以利用toInt()與toDouble()等方法來實現,如:
void main()
{
int a = 10;
print(a); // Output: 10
double b = 3.14;
print(b); // Output: 3.14
// double赋值给double
double c = b;
print(c); // Output: 3.14
// int赋值给double
b = a.toDouble();
print(b); // Output: 10.0
num d = 5.6;
print(d); // Output: 5.6
// num赋值给int
a = d.toInt();
print(a); // Output: 5
}
2.3.布林型別-bool
與C/C++中的bool基本類似.
- 場景:當我們需要一個屬性來表示當前為真(true)或假(false)的時候,需要使用bool關鍵字宣告
- 需求:聲明當前自己是否已經完成作業
- 語法:
bool 属性名 = true/false;
void main()
{
bool isFinishWork = false;
print('我的工作完成状态为:$isFinishWork'); //Output: 我的工作完成状态为:false
isFinishWork = true;
print('我的工作完成状态为:$isFinishWork'); //Output: 我的工作完成状态为:true
}
2.4.列表型別-List
2.4.1.List
與C/C++中的STL向量std::vector基本類似.(注意,和std::list並不像)
而std::vector我們經常把他用作不定长数组,所以你不理解std::vector的時候把他當作一個高階的数组也可以.
本節肯定講不完List的所有用法,但是大多數常用的用法都會講到,你忘記了可以隨時去查文件就行,不用每種用法都硬背下來,用的多的用法自然你就記住了,現在你只需要學完一遍,並知道有那麼個東西即可.
基礎用法:
- 場景:當一個變數需要儲存多個值的時候,可以使用列表型別List
- 需求:一個班級的學生用List儲存,支援對學生的查詢、新增、刪除、迴圈
- 語法:List 屬性名 = [‘學生1’, ‘學生2’];
常用用法1:
- 在尾部新增-
add(内容) - 在尾部新增一個列表-
addAll(列表) - 刪除滿足內容的第一個-
remove(内容) - 刪除最後一個-
removeLast() - 刪除索引範圍內資料-
removeRange(start,end)注意:end不包含在刪除範圍內
常用用法2:
下面會列舉幾個方法與屬性,學過物件導向你肯定知道是啥,如果沒學過,我就先簡單說一下:
类-class的声明与定义
对象-class类型的实例,(不好理解也可以理解为class类型的变量)
方法-class里的函数
属性-class里的变量
- 迴圈(方法)-
forEach((item) {}); - 是否都滿足條件(方法)-
every((item) { return 布尔值 }); - 篩選出滿足條件的資料(方法)-
where((item) { return 布尔值 }); - 列表的長度(屬性)-
length - 最後一個元素(屬性)-
last - 第一個元素(屬性)-
first - 是否為空(屬性)-
isEmpty
void main(List<String> args)
{
List students = ["张三", "李四", "王五"];
print(students); // Output: [张三, 李四, 王五]
students.add("新同学"); // 在尾部进行添加
print(students); // Output: [张三, 李四, 王五, 新同学]s
students.addAll(["新来的同学1", "新来的同学2"]); // 在尾部添加一个列表
print(students); // Output: [张三, 李四, 王五, 新同学, 新来的同学1, 新来的同学2]
students.add("新同学"); // 在尾部进行添加
print(students); // Output: [张三, 李四, 王五, 新同学, 新来的同学1, 新来的同学2, 新同学]
students.remove("新同学"); // 删除满足内容的第一个
print(students); // Output: [张三, 李四, 王五, 新来的同学1, 新来的同学2, 新同学]
// 删除最后一个同学
students.removeLast(); // 删除最后一个
print(students); // Output: [张三, 李四, 王五, 新来的同学1, 新来的同学2]
// 删除前两个同学
// start开始的索引 end结束的索引-不包含在删除范围内
students.removeRange(0, 2);
print(students); // Output: [王五, 新来的同学1, 新来的同学2]
// forEach针对每个列表每个数据进行操作
students.forEach((item)
{
// 书写逻辑
print(item); // Output: 王五
// 新来的同学1
// 新来的同学2
});
// 是不是所有的同学都以新为开头
bool isAllStartWithNew = students.every((item)
{
return item.toString().startsWith("新"); // 返回一个条件
});
print(isAllStartWithNew); // Output: false (因为王五不以新开头,需要满足所有的同学都以新开头才会返回true)
// 筛选出所有的以新开头的同学呢
List newStudents = students.where((item)
{
return item.toString().startsWith("新");
}).toList();
print(newStudents); // Output: [新来的同学1, 新来的同学2]
// List常用的一些属性 方法() .属性
// 列表的长度
print(students.length); // Output: 3
// 列表的第一个
print(students.first); // Output: 王五
// 列表的最后一个
print(students.last); // Output: 新来的同学2
// 列表是否是空的
print(students.isEmpty); // Output: false (因为列表中有数据)
}
2.4.2.main函式入口引數
除了上面的程式碼外可以看到void main(List<String> args)裡有引數了,這個其實類似C/C++裡的int main(int argc, char* argv[])
| 對比點 | C/C++ | Dart |
|---|---|---|
| 引數個數 | argc |
args.length |
| 引數陣列 | argv[] |
List<String> |
| 是否包含程式名 | ✅ argv[0] 是程式名 | ❌ 不包含 |
| 型別安全 | ❌ char* | ✅ String |
| 記憶體管理 | 手動 | 自動 |
例如
dart run app.dart hello world
此時
args[0] = "hello"
args[1] = "world"
2.5.字典型別-Map
類似C++的std::map.
基礎用法:
- 一個key對應一個value
- 語法1:Map 屬性名 = { key: value };
- 語法2:
字典[key] 可以取值和赋值
常用用法:
- 迴圈-
forEach - 在新增一個字典-
addAll - 是否包含某個key-
containsKey - 刪除某個key-
remove - 清空-
clear
void main(List<String> args)
{
Map transMap = {"lunch": '午饭', "morning": "早上", "hello": '你好'};
print(transMap);
// 通过英文找到对应中文的描述
print(transMap["morning"]);
transMap["hello"] = "你非常好";
print(transMap["hello"]);
// 字典里面有很多对应关系
transMap.forEach((key, value) {
print("$key,$value");
});
// addAll 给当前字典添加一个字典
transMap.addAll({"fine": "非常好"});
print(transMap);
// containesKey判断字典中是否包含某个key
print(transMap.containsKey("fine"));
transMap.remove("fine");
print(transMap);
// 清空字典
transMap.clear();
print(transMap);
}
2.6.動態型別-dynamic
類似C++的std::any
- 定義:Dart語言中,dynamic用來宣告動態型別
- 特點:允許變數執行時自由改變型別, 同時繞過編譯時的靜態檢查
- 語法1:
dynamic 属性名 = 值;
void main(List<String> args)
{
// dynamic 可以动态的改变类型
dynamic name = "张三";
print(name);
name = 123;
print(name);
}
只有你自己100%認為你寫的是對的,再用dynamic,否則別用dynamic,不然可能會出現很多錯誤.
2.7.自動推導型別-var
類似C/C++的auto.
這個關鍵字可以自動推導變數的型別.
- 關鍵字:var
- 語法:
var 变量名 = 值/表达式; - 注意:使用var宣告的變數,其型別在第一次賦值之後確定,不能再賦值其他型別的值
void main(List<String> args)
{
var name = '张三';
print(name); // Output: 张三
name = '李四';
print(name); // Output: 李四
var age = 30;
print(age); // Output: 30
var isStudent = true;
print(isStudent); // Output: true
var height = 1.75;
print(height); // Output: 1.75
}
Dart中的動態型別-dynamic和var的區別:
- dynamic: 執行時可自由改變型別,無編譯檢查,方法和屬性直接呼叫
- var: 根據初始值進行推斷型別,確定型別後型別確定,有編譯檢查,僅限推斷的屬性和方法
2.8.常量宣告-const/final
2.8.1.const
類似C++的constexpr.
- 關鍵字:const
- 語法:const 屬性名 = 值/表示式;
- 特點:const是程式碼編譯前被確定,不允許表示式中有變數存在,必須為常量或者固定值
void main(List<String> args)
{
const int a = 10;
const double b = 3.14;
const String c = "Hello, Dart!";
print("Value of a: ${a}"); // Output: Value of a: 10
print("Value of b: ${b}"); // Output: Value of b: 3.14
print("Value of c: ${c}"); // Output: Value of c: Hello, Dart!
}
2.8.2.final
類似C++的const.
- 關鍵字:final
- 語法:final 屬性名 = 值/表示式;
- 特點:final變數在執行時被初始化,其值設定後不可更改
void main(List<String> args)
{
final time = DateTime.now();
print('Current time: $time'); // Current time: 2026-02-16 20:53:53.045010
}
- 變數:當需要儲存一個變化的資料需要使用var來宣告變數
- 編譯時常量:當需要儲存一個不變的資料,且在編譯時就確定,需要使用const宣告常量
- 執行時常量:當需要儲存一個不變的資料,但是在執行時才確定,需要使用final宣告常量
| 概念 | Dart | C++ | 是否編譯期常量 | 是否可執行期確定 | 是否物件不可變 |
|---|---|---|---|---|---|
| 只賦值一次 | final |
const |
❌ | ✅ | ❌ |
| 編譯期常量 | const |
constexpr |
✅ | ❌ | ✅(Dart更強) |
| 只讀變數 | 無完全等價 | const |
❌ | ✅ | ❌ |
3.空安全機制
- 定義:在Dart語言中,通過編譯靜態檢查將執行時空指標提前暴露
- 特點:將空指標異常從執行時提前至編譯時,減少線上崩潰
常用空安全運算子
| 運算子 | 符號 | 作用 | 示例 |
|---|---|---|---|
| 可空型別 | ? |
宣告可空變數 | String? → 允許 String 或 null |
| 安全訪問 | ?. |
物件為 null 時跳過操作,返回 null | user?.name → 若 user 為 null 則返回 null |
| 非空斷言 | !. |
開發者保證變數非空(否則執行時崩潰) | name!.length → 斷言 name 非空 |
| 空合併 | ?? |
左側為 null 時返回右側預設值 | name ?? "Guest" → name 為 null 時返回 "Guest" |
| 空合併賦值 | ??= |
變數為 null 時才賦值 | name ??= "Guest" |