跳到正文

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"