我們以外層為中括號
包裹元素,並以逗號分隔的方式來定義陣列,下述兩種都是宣告陣列的方式
var list = [1, 2, 3]; //數字陣列
var list = [
'Car',
'Boat',
'Plane',
]; //字串陣列,最後的逗號不影響宣告,但可以防範複製錯誤
List宣告範例
在下述例子中,我們可以看到基本的List性質,包含陣列長度計算、陣列位址計算、修改方式等。
[0]~[陣列長度-1]
,以下述範例而言,就是[0],[1],[2]void main() {
// 創建一個 List
var list = [1, 2, 3];
// 檢查 List 的長度
print('List 的長度是 ${list.length}');
// 檢查 List 中的元素
print('List 中的元素是 $list');
// 更改 List 中的元素
list[1] = 1;//因為list是由[0]作為第一元素,因此這裡的[1]代表的是陣列中的第二個元素,也就是'2'
// 再次檢查 List 中的元素
print('List 中的元素是 $list');
}
List使用範例
我們以外層為大括號
包裹元素,並以逗號分隔的方式來定義Set
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
//鹵素包含以下幾種元素集合
var names = <String>{};//創建空集合,等義於 Set<String> names = {};
我們可以使用add()
的方式將單一元素加入原有的集合中,例如下列範例將'fluorine'加入elements 集合;或是使用addAll()
將一集合內全部元素加入另一集合中,例如下列範例將alogens 集合中的所有元素加入到 elements 集合中;而同樣的,我們也可以用.length
來得到集合長度
void main() {
// 定義 halogens 集合,包含氟、氯、溴、碘和砹等元素
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
// 定義一個空的 elements 集合
var elements = <String>{};
// 將 'fluorine' 加入 elements 集合
elements.add('fluorine');
// 將 halogens 集合中的所有元素加入到 elements 集合中
elements.addAll(halogens);
// 確保 elements 集合的長度為 5
assert(elements.length == 5);
// 輸出 halogens 集合的元素
print('Halogens: $halogens');
// 輸出 elements 集合的元素
print('Elements: $elements');
}
Set基本性質範例
我們以外層為大括號
包裹元素,並以逗號分隔每組key-value值的方式來定義,每組key與value間以分號:
作為連結
var gifts = {
// Key欄位: Value欄位,Key欄位紀錄禮物序號,Value欄位紀錄禮物內容
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
// Key欄位: Value欄位,Key欄位紀錄原子序,Value欄位紀錄元素名稱
2: 'helium',
10: 'neon',
18: 'argon',
};
Map宣告範例
而我們也可以將"gifts" ,"nobleGases"變數用Map構造函式Map<String, String>
與Map<int, String>
的方式進行宣告,
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map<int, String>();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
Map宣告範例
我們可以用[]=
的方式來新增一個key-value對,並且用.length
的方式來確認長度。尤以下範例中,我們首先定義了一個gifts的Map物件,一開始只有一個key-value對,而後我們再新增第二個禮物(中括號內的為key值,而等號右方的為value值),在兩次的print(gifts)中我們可以看出差別,而中間的assert()函式可以幫助我們進行條件檢查(條件不符合時會出現警告)
void main() {
// 定義一個名為 "gifts" 的 Map 物件,包含一個 key-value 對。
var gifts = {'first': 'partridge'};
// 在 Map 中新增一個 key-value 對,新增第二個禮物設為 'calling birds'。
gifts['second'] = 'calling birds';
print(gifts);//印出的gifts裡面有 first和second
// 斷言:檢查第一個禮物是否是 'partridge'。
assert(gifts['first'] == 'partridge');
// 斷言:檢查第三個禮物是否為 null。
assert(gifts['third'] == null);
// 再次在 Map 中新增一個 key-value 對,新增第三個禮物設為 'doll'
gifts['third'] = 'doll';
print(gifts);//印出的gifts裡面有 first,second和third
// 斷言:檢查 Map 的長度是否為 3。
assert(gifts.length == 3);
}
Map基本性質範例
...
和 ?...
,前者用於非空情況,後者用於可能為空的情況以下示範兩種範例
void main() {
//---------"..."展開運算符----------
// 定義一個整數串列 list1
var list1 = [1, 2, 3];
// 使用展開運算符將 list1 的元素展開到 list2 中
var list2 = [0, ...list1, 4, 5];
// 輸出 list2 的內容
print('展開運算符範例: $list2'); // 輸出:[0, 1, 2, 3, 4, 5]
//---------"?... "安全展開運算符----------
// 定義一個可能為 null 的整數串列 nullableList
List<int>? nullableList = null;
// 使用安全展開運算符將 nullableList 的元素展開到 list3 中
var list3 = [0, ...?nullableList];
// 輸出 list3 的內容
print('安全展開運算符範例: $list3'); // 輸出:[0]
}
展開運算符範例
我們可以透過在集合(如串列或 Map)中加入if, for的方式來宣告,以便簡化宣告流程的判斷或迭代,我們可以由以下範例看到三種用法,包含if集合、if-case集合與for迴圈集合用於列表的用法
void main() {
//---------if集合用於列表範例-------------
bool promoActive = true;
// 建立一個導航串列 "nav",並加入if條件判斷
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
print('if集合用於列表範例: $nav');
// promoActive為true,條件成立,輸出:[Home, Furniture, Plants, Outlet]
//---------if-case集合用於列表範例---------
String login = 'Manager';
// 建立另一個導航串列 "navWithLogin",並加入if-case判斷
var navWithLogin = ['Home', 'Furniture', 'Plants', if (login == 'Manager') 'Inventory'];
print('if-case集合用於列表範例: $navWithLogin');
// login為'Manager',條件成立,輸出:[Home, Furniture, Plants, Inventory]
//---------for迴圈集合用於列表範例---------
var listOfInts = [1, 2, 3];
// 建立一個字串串列 "listOfStrings",並加入for迴圈
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
print('for迴圈集合用於列表範例: $listOfStrings');//輸出for迴圈迭代後結果
}
參考資料: Dart Language: Records
在Records中,我們使用"逗號"為括號內的每筆資料作分隔,並且可以用getter,$<position>
或指定變數的方式取值。其中,當我們使用getter時是針對沒有命名的變數進行取值,所以可以由下列範例中的$2印出'last'字串,可以看到a, b兩個已命名變數會被跳過
void main() {
var record = ('first', a: 2, b: true, 'last');
print(record.$1); // 輸出第一欄位,'first'
print(record.$2); // 輸出第二欄位,'last'(跳過命名的變數a,b)
print(record.a); // 輸出變數'a'的值
print(record.b); // 輸出變數'b'的值
}
record範例
我們由DartPad的Documentation欄位可以看到這是一個由兩個String, 一個int變數"a"與bool變數"b"組成的record變數
而我們也可以用records的方式來定義回傳的資料,下方的(int, int)
代表Records類型的註釋
(int, int) swap((int, int) record) { //用records的方式對回傳函式參數值進行規範
var (a, b) = record;
return (b, a);
}
void main() {
var (a, b) = swap((1, 2));//交換前的數字陣列是(1,2)
print('交換後的a: $a'); // 輸出2
print('交換後的b: $b'); // 輸出1
}
Records類型註釋範例
在宣告Records時,我們可以選擇連同變數與型別一起宣告的方式(用大括號
將變數類型與名稱包含)
void main() {
//--------宣告Record變數與內部變數、型別-----------
({int a, bool b}) record;//用大括號表示Records內的變數宣告
// 給予Records初始化值: (a: 123, b: true)
record = (a: 123, b: true);
print('變數a: ${record.a}'); // 輸出 a 變數的值
print('變數b: ${record.b}'); // 輸出 b 變數的值
//--------宣告Records變數與內部型別---------------
(int, bool) record2;
// 給予Record2初始化值: (a: 123, b: true)
record2 = (123, true);
print('欄位一: ${record2.$1}'); // 輸出欄位一的值
print('欄位二: ${record2.$2}'); // 輸出欄位二的值
}
在我們未宣告變數時,系統也會明確知道Records內部真值的型別
void main() {
(num, Object) pair = (42, 'a');
var first = pair.$1; // 靜態型別`num`, 運行型別`int`.
var second = pair.$2; // 靜態型別 `Object`, 運行型別 `String`.
print(first.runtimeType); // 輸出運行型別,int
print(second.runtimeType); // 輸出運行型別,String
}
Record types範例
兩個 record 相等如果它們有相同的形狀(變數集合)和相應變數的值相同。 由於命名"順序"不是 record 的形狀的一部分,因此命名變數的順序"不影響"相等性。
以下是一些概念例子:
我們可以用Records的方式來簡化具有多重回傳值的情況,以下列範例為例,可以一次性的將多種型別與函數值對應在userInfo的函式中
void main() {
// 定義一個 JSON 對象
final json = {
'name': 'Dash',
'age': 10,
'color': 'blue',
};
// 使用 record 模式獲取 name 和 age 字段的值
var (name, age) = userInfo(json);
// 輸出 name 和 age 的值
print('Name: $name');
print('Age: $age');
}
(String, int) userInfo(Map<String, dynamic> json) {
// 返回 name 和 age 字段的值
return (json['name'] as String, json['age'] as int);
}
Multiple returns範例