在上一篇,我們介紹了一些資料的基本型態,今天我們來介紹一下Dart 有哪些內建的資料型態,我們可以在Dart 上直接用這些內建的資料型態,去新增我們的物件,而這些物件都能夠使用它型態的特定方法,即API (Application Programming Interface),可以理解成是別人已經寫好的方法,提供給我們,不需要了解方法的原理,會使用就好。
Dart 的內建的資料型態有數值型 (num)、布林型 (bool)、字串 (String)、Map、List、Runes、Symbols,有一些資料型態已在上一篇介紹過,下面我們來看看這些資料型態怎麼使用吧
數值型有兩種型態,一種是整數,另一種是浮點數
main(){
num pi = 3; //pi 型態為num,值可為 int
pi = 3.14; //pi 型態為num,值可為 double
print("pi = $pi"); //印出 pi = 3.14
}
為集合資料型別,在其他常見的程式語言見作陣列 (array),而在Dart 中陣列就是List
物件,所以一般稱為lists
,用[ ]
表示List
的內容,可用明確的資料型態宣告,未宣告元素型別時Dart 會自行判斷
main() {
var list = [1, 2, 3]; //由Dart 推斷為 List<int> 型態
//list.add("4"); 會報錯,Error: The argument type 'String' can't be assigned to the parameter type 'int'.
//使用 List型態類別的方法
print(list.length);// 印出3,共有三筆資料
List list2 = [1, 2, 3]; //為指定 List型態時,推斷為dynamic
list2.add("4"); //不會出錯
List<int> list3 = [1, 2, 3]; //為明確的 List<int> 型態
//list3.add("4"); 會報錯,Error: The argument type 'String' can't be assigned to the parameter type 'int'.
var list4 = List(3); //此方法為建立固定長度的List,不能移除或者增加
list4[0] = 1;
list4[1] = 2;
list4[2] = 3;
print(list4); //印出 [1, 2, 3]
//常數的List,不能對值做改變
var constantList = const [1, 2, 3];
// constantList[1] = 1; // 會報錯
}
集合資料皆由位置索引(index
) 0 開始數第一個資料,最後一個資料的index
即為 集合資料總長度 -1
main() {
var list = [1, 2, 3];
print("list[0] = ${list[0]}"); //印出 list[0] = 1
print("list[1] = ${list[1]}"); //印出 list[1] = 2
print("list[2] = ${list[2]}"); //印出 list[2] = 3
}
在Dart 2.3後,spread operator (...
) 以及 null-aware spread operator (...?
),可以插入另一個集合的資料
main() {
var list = [1, 2, 3];
var list2 = [0, ...list];
print(list2); //印出 [0, 1, 2, 3]
var list3;
var list4 = [0, ...?list3];
print(list4); //印出 [0]
}
Dart 2.2 後新增,用{ }
表示Set
的內容,用於相同類型物件的集合,可於型別宣告後或{ }
前以< >
宣告元素型別,未宣告元素型別時Dart 會自行判斷
與List
不同,Set
是無序的,因此於Set
無法使用[index]
取得或設定指定索引的值,同時因為沒有索引值區分,Set
所有元素是唯一的,故無法重複加入同樣的值,新增重複的值會被省略
Set
的語法跟Map
很像 (Map
等等會介紹),但Set
是在Dart 2.2 後才新增,故若用未明確宣告資料型態來宣告{ }
的話,Dart 會推斷型態為Map
void main() {
var set1 = {1, 2, 3}; // 推斷為 Set<int>
var set2 = {}; // 推斷為 Map<dynamic, dynamic>, 不是 SET
var set3 = <int>{}; // 為 Set<int>
// 與List與Map相同,可使用.length方法取得元素個數
print(set1.length); //印出 3
set1.add(3); //新增重複的值,會被省略
print(set1.length); //印出 3
}
Map
是使用key-value的方式來儲存的資料型態,key 和value 可以是任何型別的物件,其中 key 是唯一,不能重覆,但值可以重複
main(){
var gifts = {
// Key: Value
'first': 'partridge',
//'first': 'abcdefg', //會報錯,key重複了
'second': 'turtledoves',
'fifth': 'golden rings'
}; //推斷型態為 Map<String, String>
var gifts2 = Map(); //推斷型態為 Map<dynamic, dynamic>
gifts2['first'] = 'partridge'; // 新增新的一對 key-value
gifts2['second'] = 'turtledoves';
gifts2['fifth'] = 'golden rings';
var gifts3 = {}; //推斷型態為 Map<dynamic, dynamic>
gifts3['first'] = 'partridge';
gifts3['second'] = 'turtledoves';
gifts3['fifth'] = 'golden rings';
//gifts、gifts2、gifts3,這三個物件內容都一樣
//常數的Map,不能對值做改變
Map<int,String> constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
// constantMap[2] = 'Helium'; 會報錯
}
Runes
是代表字串的UTF-32 code points,Unicode為每一個字元、標點符號、表情符號等都定義了一個唯一的數值,要在String
顯示32-bit Unicode 的值,也就是說在書寫系統中,每一個字母,數字都有唯一的數值,而由於在Dart 字串是UTF-16 code units 字元序列,所以在字串表達32-bit Unicode值就需要新的語法,通常用\uXXXX
的方式表示Unicode code point,這裡的XXXX是4個16進位制的數。
void main() {
Runes heart = '\u2665';
Runes laugh = '\u{1f600}';
print(String.fromCharCodes(heart) + ' ' + String.fromCharCodes(laugh)); //印出 ♥ ?
String heart2 = '\u2665';
String laugh2 = '\u{1f600}';
print(heart2 + ' ' + laugh2); //印出 ♥ ?
}
用來代表Dart 程式宣告的操作符或者識別符號,使用到的機率很小,但是此功能對於通過名字來引用識別符號的情況還是非常有用的,像是混淆後的程式碼,識別符號的名字被混淆了,但是Symbol
的名字一樣不會改變
void main() {
//有兩種新建Symbol的方式:Symbol('name') 或 #name
print(Symbol('a') == #a); // 印出 true, == 是相等的運算符號,後面會介紹
var name = 'test';
Symbol symbol = #name;
print(symbol); //印出 Symbol("name")
print(#name); //印出 Symbol("name")
}
判斷式用,為true 或 false
指定運算子:=
算術運算子:+ (加),- (減),* (乘),/ (除),% (取餘數)
算術指派運算子:+=,-=,*=,/=,%=
void main() {
int x = 1;
int y = 2;
//x += y; 即 x = x + y
print("x += y = ${x += y}"); //印出 x += y = 3
}
比較運算子:
< ( 小於 ),<= ( 小於等於 ),> ( 大於 ),>= ( 大於等於 ),== ( 等於 ),!= ( 不等於 )
邏輯運算子:
&& (且),|| (或),!(非),^(xor,相同及false)
void main() {
print(true ^ true); //印出false
print(false ^ true); //印出true
print(true ^ false); //印出true
print(false ^ false); //印出false
}
三元運算子:
語法:
條件 ? 符合 : 不符合
void main() {
int a = 11;
int b = a > 9 ? 99 : 100;
print(b); //印出 99
int c = a > 12 ? 99 : 100;
print(c); //印出 100
}
遞增運算子 ( ++ ) 與 遞減運算子 ( -- )
i ++ 與 ++ i 即是 i = i + 1,i -- 與 i -- 即是 i = i -1 ;
++ (--) 在後面即是後置遞增 (減) 在運算後做,在前面即是前置遞增 (減) 在運算前先做
想看詳細介紹的可以看此範例
void main() { int x = 1, y = 1; bool ex1 = ++x > ++y; /* x = x + 1; x = 1 + 1 -> 2 y = y + 1; y = 1 + 1 -> 2 x > y; 2 > 2 -> false ex1為false */ print(ex1); //印出 false // reset x跟y x = 1; y = 1; bool ex2 = ++x > y++; /* x = x + 1; x = 1 + 1 -> 2 x > y; 2 > 1 -> true y = y + 1; y = 1 + 1 -> 2 ex2為true */ print(ex2); //印出 true // reset x跟y x = 1; y = 1; bool ex3 = x++ > ++y; /* y = y + 1; y = 1 + 1 -> 2 x > y; 1 > 2 -> false x = x + 1; x = 1 + 1 -> 2 ex3為false */ print(ex3); //印出 false int a = 7; int b = ++a; //b=8 int c = 7; int d = c--; //d=7 }
if else
void main() {
/*
if(布林1) {
//若布林1為true即執行此區塊,執行完不會執行其他區塊
}else if(布林2){
//若布林1為false以及布林2為true即執行此區塊,執行完不會執行其他區塊
}else{
//若布林1以及布林2都不是true才執行此區塊
}
*/
//大括號可以被省略但只有if下方的第一行會被視為if裡面的內容
int a = 0;
if (false) a = 2; // a = 0
if (false)
a = 3; // 在判斷式區域內,故應該執行,但條件為false,a 還是 0
print(a); // 已不在判斷式區域內,故有執行,a = 4
}
switch
使用==
比較int
、String
、Enum
(後面介紹)、或者編譯時常量,每個非空case
語句都必須有一個break
。不然就得使用continue
、throw
、return
,當沒有case
可以匹配時,可以使用``default` 語句來匹配這種預設情況
main(){
int a = 11;
switch (a) {
case 2:
print("2");
break;
case 11:
print("A");
break;
case 22:
print("B");
break;
default:
print("else");
}
//印出 A
var command = 'CLOSED';
switch (command) {
case 'CLOSED': // 通過空case 語句
case 'NOW_CLOSED':
// CLOSED 和 NOW_CLOSED,都會執行
print("NOW_CLOSED"); //印出 NOW_CLOSED
break;
}
}
for(初始值 ; 判斷是否停止或繼續做的條件 ; 如何讓迴圈停止的規則){
欲執行的步驟
}
void main() {
for (int x = 0; x < 5; x++) {
print("x = $x");
}
//印出
//x = 0
//x = 1
//x = 2
//x = 3
//x = 4
}
for each
void main() {
//使用foreach迴圈 list 和 Set都可以用這種方式
List numbers = [1, 2, 3, 4, 5];
numbers.forEach((number) => print(number));
/* 印出
1
2
3
4
5
*/
}
for in
void main() {
//使用for in迴圈,一般List和Set都是用這種方式
List numbers = [1, 2, 3, 4, 5];
for (var number in numbers) {
print(number);
}
/* 印出
1
2
3
4
5
*/
}
while
while(判斷是否停止或繼續做的條件) {
欲執行的步驟
}
void main() {
int x = 0;
while (x < 5) {
print("x = ${x++}");
}
//印出
//x = 0
//x = 1
//x = 2
//x = 3
//x = 4
}
do while
do{
欲執行的步驟
} while(判斷是否停止或繼續做的條件)
void main() {
int x = 6;
do {
print("x = ${x++}");
} while (x < 5);
//印出 x = 6
}
brea
與continue
void main() {
for (int x = 0; x < 10; x++) {
if (x == 2) {
continue; // x = 2時,跳過這次
} else if (x == 5) {
break; // x = 5時,中斷
}
print("x = $x");
}
//印出
//x = 0
//x = 1
//x = 3
//x = 4
}
Assert
如果條件式結果不滿足需求,則可以使用assert
語句打斷程式碼的執行,只有在debug
模式才能使用,若
assert
錯誤,會執行失敗並拋出異常
今天補充完了資料型態,也介紹了一些基本運用,已經有程式基礎的應該很好上手,第一次學的人,建議搭配 DartPad,多做練習