第 4 節
Dart語言教程
0瀏覽次數0訪問次數--跳出率--平均停留
代碼規範
幾乎和C/C++一模一樣.
- 擴展名: dart語言文件後綴以
.dart結尾 - 入口:dart文件的入口方法為main方法
- 分號:dart文件中絕大部分語句都需要加分號結尾,像
{ }後通常不加分號
Dart的變量
該節與C/C++高度相似.
字符串類型-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
}
數字類型-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
}
布爾類型-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
}
列表類型-List
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 (因为列表中有数据)
}
main函數入口參數
除了上面的代碼外可以看到void main(List<String> args)裡有參數了,這個其實類似C/C++裡的int main(int argc, char* argv[])
| 對比點 | C/C++ | Dart |
|---|---|---|
| 參數個數 | argc | args.length |
| 參數數組 | argv[] | List<String> |
| 是否包含程序名 | ✅ argv0 是程序名 | ❌ 不包含 |
| 類型安全 | ❌ char* | ✅ String |
| 內存管理 | 手動 | 自動 |
例如
dart run app.dart hello world
此時
args[0] = "hello"
args[1] = "world"
字典類型-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);
}
動態類型-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,不然可能會出現很多錯誤.
自動推導類型-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: 根據初始值進行推斷類型,確定類型後類型確定,有編譯檢查,僅限推斷的屬性和方法
常量聲明-const/final
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!
}
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 | ❌ | ✅ | ❌ |
空安全機制
- 定義:在Dart語言中,通過編譯靜態檢查將運行時空指針提前暴露
- 特點:將空指針異常從運行時提前至編譯時,減少線上崩潰
常用空安全操作符
| 操作符 | 符號 | 作用 | 示例 |
|---|---|---|---|
| 可空類型 | ? | 聲明可空變量 | String? → 允許 String 或 null |
| 安全訪問 | ?. | 對象為 null 時跳過操作,返回 null | user?.name → 若 user 為 null 則返回 null |
| 非空斷言 | !. | 開發者保證變量非空(否則運行時崩潰) | name!.length → 斷言 name 非空 |
| 空合併 | ?? | 左側為 null 時返回右側默認值 | name ?? "Guest" → name 為 null 時返回 "Guest" |
| 空合併賦值 | ??= | 變量為 null 時才賦值 | name ??= "Guest" |