- 原文部落格地址: Flutter開發之Dart語法基礎
Dart
是谷歌在 2011 年推出的程式語言,是一種結構化Web
程式語言,允許使用者通過Chromium
中所整合的虛擬機器(Dart VM
)直接執行Dart
語言編寫的程式,免去了單獨編譯的步驟- 以後這些程式將從
Dart VM
更快的效能與較低的啟動延遲中受益 Dart
從設計之初就為配合現代web
整體運作而考慮,開發團隊也同時在持續改進Dart
向JavaScript
轉換的快速編譯器Dart VM
以及現代JavaScript
引擎(V8 等)都是Dart
語言的首選目標平臺Dart
語言和Swift
語言有很多的相似之處
重要概念
在學習Dart
語言之前, 先了解一些Dart
相關的一些概念:
- 在
O-Objective
中有一切皆物件的說法, 這句話在Dart
中同樣適用- 所有能夠使用變數引用的都是物件, 每個物件都是一個類的例項
- 在
Dart
中 甚至連 數字、方法和null
都是物件 - 所有的物件都繼承於
Object
類
Dart
動態型別語言, 儘量給變數定義一個型別,會更安全,沒有顯示定義型別的變數在debug
模式下會型別會是dynamic
(動態的)Dart
會在執行之前解析你的所有程式碼,指定資料型別和編譯時的常量,可以提高執行速度Dart
中的類和介面是統一的,類即介面,你可以繼承一個類,也可以實現一個類(介面),自然也包含了良好的物件導向和併發程式設計的支援Dart
函式- 支援頂級函式 (例如
main()
) - 支援在類中定義函式, 如靜態函式和例項函式
- 還可以在方法中定義方法(巢狀方法或者區域性方法)
- 支援頂級函式 (例如
- 類似的,
Dart
支援頂級變數,以及依賴於類或物件(靜態變數和例項變數)變數。例項變數有時被稱為域或屬性 Dart
不具備關鍵字public
,protected
和private
。如果一個識別符號以下劃線(_)
開始,那麼它和它的庫都是私有的- 識別符號可以字母或(_)開始,或者是字元加數字的組合開頭
以上只是大概說明了一些
Dart
中的重要概念, 具體的語法使用, 請看下文
基本語法
註釋
Dart
的註釋分為3種:單行註釋、多行註釋、文件註釋
- 單行註釋以
//
開頭 - 多行註釋以
/*
開頭,以*/
結尾 - 文件註釋以
///
或者/**
開頭
分號;
- 分號用於分隔
Dart
語句 - 通常我們在每條可執行的語句結尾新增分號
- 使用分號的另一用處是在一行中編寫多條語句
- 在
Dart
中,用分號來結束語句是必須的, 不加分則會報錯
其他語法
- 按照
Dart
的程式設計規範,使用2個空格來縮排 - 輸出語句使用
print(Object)
變數和常量
變數
使用var
、Object
或dynamic
關鍵字宣告變數
var name = 'name';
dynamic name1 = 'name1';
String name2 = 'name2';
// 變數的賦值
name = 'a';
name1 = 'a1';
name2 = 'a2';
複製程式碼
未初始化的變數的初始值為null
, 即使是數字也是如此,因為在Dart
中數字也是一個物件
var name;
dynamic name1;
String name2;
複製程式碼
可選型別
在宣告變數的時候,你可以選擇加上具體的型別:
String name2 = 'name2';
複製程式碼
- 這種方式可以更加清晰的表達你想要定義的變數的型別, 編譯器也可以根據該型別為你提供程式碼補全、提前發現 bug 等功能
- 注意: 對於區域性變數,這裡遵守 程式碼風格推薦 部分的建議,使用
var
而不是具體的型別來定義區域性變數
常量
- 常量使用
final
或者const
- 一個
final
變數只能賦值一次 - 一個
const
變數是編譯時常量 - 例項變數可以為
final
但是不能是const
final
final
修飾的變數(即常量2)
final age = 10;
final int age1 = 20;
// final修飾的變數不能重新賦值, 會報錯
age = 20;
age1 = 30;
複製程式碼
const
const
變數為編譯時常量- 如果在類中使用
const
定義常量,請定義為static const
- 使用
const
定義的常量, 可以直接給定初始值,也可以使用其他const
變數的值來初始化其值
// const
const m1 = 12;
const double m2 = 23;
const m3 = m1 + m2;
// final修飾的變數不能重新賦值, 會報錯
m1 = 10;
m2 = 1.02;
複製程式碼
操作符
算術操作符
Dart
支援常用的算術操作符
操作符 | 解釋 |
---|---|
+ |
加號 |
– |
減號 |
-expr |
負號 |
* |
乘號 |
/ |
除號(值為double 型別) |
~/ |
除號,但是返回值為整數 |
% |
取模 |
示例:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 結果是double型別
assert(5 ~/ 2 == 2); // 結果是integer型別
assert(5 % 2 == 1); // 餘數
複製程式碼
自加自減
Dart
還支援自加自減操作
++var
: 先自加在使用var++
: 先使用在自加--var
: 先自減在使用var--
: 先使用在自減
示例
var a = 0, b = 0;
b = a++;
print('a = $a, b = $b'); //a = 1, b = 0
b = ++a;
print('a = $a, b = $b'); //a = 2, b = 2
b = a--;
print('a = $a, b = $b'); //a = 1, b = 2
b = --a;
print('a = $a, b = $b'); //a = 0, b = 0
複製程式碼
關係操作符
運算子 | 含義 |
---|---|
== |
等於 |
!= |
不等於 |
> |
大於 |
< |
小於 |
>= |
大於等於 |
<= |
小於等於 |
- 要測試兩個物件代表的是否為同樣的內容,使用
==
操作符 - 在某些情況下,你需要知道兩個物件是否是同一個物件, 使用
identical()
方法
external bool identical(Object a, Object b);
複製程式碼
型別判定操作符
型別判定操作符是在執行時判定物件型別的操作符
操作符 | 解釋 |
---|---|
as |
型別轉換 |
is |
如果物件是指定的型別返回 True |
is! |
如果物件是指定的型別返回 False |
- 只有當
obj
實現了T
的介面,obj is T
才是true
。例如obj is Object
總是true
- 使用
as
操作符把物件轉換為特定的型別 - 可以把
as
它當做用is
判定型別然後呼叫 所判定物件的函式的縮寫形式
if (emp is Person) { // Type check
emp.firstName = 'Bob';
}
// 上面程式碼可簡化為
(emp as Person).firstName = 'Bob';
複製程式碼
注意: 如果
emp
是null
或者不是Person
型別,則第一個示例使用is
則不會執行條件裡面的程式碼,而第二個情況使用as
則會丟擲一個異常; 所以在不缺定emp
是否為空的情況下, 安全起見, 建議使用第一種方式
賦值操作符
= |
–= |
/= |
%= |
>>= |
^= |
+= |
*= |
~/= |
<<= |
&= |
示例:
// 給 a 變數賦值
a = value;
// 複合賦值操作符
a += b; // 等價於a = a + b;
// 如果 b 是 null,則賦值給 b;
// 如果不是 null,則 b 的值保持不變
b ??= value;
// 如下所示:
var s;
print(s); // null
print(s ?? 'str'); // str
s ??= 'string';
print(s); // string
複製程式碼
邏輯操作符
可以使用邏輯操作符來 操作布林值:
!expr
: 對錶達式結果取反(true 變為 false ,false 變為 true)||
: 邏輯 OR&&
: 邏輯 AND
條件表示式
condition ? expr1 : expr2
// 如果 condition 是 true,執行 expr1 (並返回執行的結果); 否則執行 expr2 並返回其結果
expr1 ?? expr2
// 如果 expr1 是 non-null,返回其值; 否則執行 expr2 並返回其結果
複製程式碼
示例:
String toString() => msg ?? super.toString();
// 上面的程式碼等價於
String toString() => msg == null ? super.toString() : msg;
// 等價於
String toString() {
if (msg == null) {
return super.toString();
} else {
return msg;
}
}
複製程式碼
級聯操作符
級聯操作符 (..
) 可以在同一個物件上 連續呼叫多個函式以及訪問成員變數。 使用級聯操作符可以避免建立 臨時變數, 並且寫出來的程式碼看起來 更加流暢
querySelector('#button') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
複製程式碼
第一個方法querySelector()
返回了一個selector
物件。 後面的級聯操作符都是呼叫這個物件的成員, 並忽略每個操作 所返回的值
// 上面程式碼等價於
var button = querySelector('#button');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
複製程式碼
級聯呼叫也可以巢狀:
final addressBook = (new AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (new PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
複製程式碼
注意:嚴格來說,兩個點的級聯語法不是一個操作符, 只是一個Dart
特殊語法。
流程控制語句
在Dart
中可以使用下面的語句來控制Dart
程式碼的流程:
if-else
for
和for-in
while
和do-while
switch
assert
break
和continue
try-catch
和throw
if-else
Dart
支援if
語句以及可選的else
if (a == 0) {
print('a = 0');
} else if (a == 1) {
print('a = 1');
} else {
print('a = 2');
}
複製程式碼
注意點: 上述程式碼中的條件控制語句的結果必須是布林值
for
可以使用標準的for
迴圈, List
和Set
等實現了Iterable
介面的類還支援for-in
形式的遍歷:
var arr = [0, 1, 2];
// for迴圈
for (var i = 0; i < arr.length; i++) {
print(arr[i]);
}
// for-in迴圈
for (var x in arr) {
print(x);
}
複製程式碼
While
和do-while
// while 迴圈在執行迴圈之前先判斷條件是否滿足:
while (c == 0) {
print('c = $c');
}
// 而do-while迴圈是先執行迴圈程式碼再判斷條件:
do {
print('c = $c');
} while (c == 0);
複製程式碼
Break
和continue
使用break
來終止迴圈:
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
複製程式碼
使用continue
來開始下一次迴圈
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
複製程式碼
Switch
Dart
中的Switch
語句使用==
比較integer
、string
、或者編譯時常量- 比較的物件必須都是同一個類的例項, 比較適合列舉值
- 每個非空的
case
語句都必須有一個break
語句 - 另外還可以通過
continue
、throw
或者return
來結束非空case
語句 - 當沒有
case
語句匹配的時候,可以使用default
語句來匹配這種預設情況 - 每個
case
語句可以有區域性變數,區域性變數只有在這個語句內可見
var command = 'OPEN';
switch (command) {
case 'CLOSED':
print('CLOSED');
break;
case 'APPROVED':
print('APPROVED');
// break;
// 這裡非空的case, 沒有break會報錯
case 'DENIED':
// 這裡空的case, 可以不要break
case 'OPEN':
print('OPEN');
continue nowClosed;
//如果你需要實現這種繼續到下一個 case 語句中繼續執行,則可以 使用 continue 語句跳轉到對應的標籤(label)處繼續執行:
nowClosed:
case 'PENDING':
print('PENDING');
break;
default:
print('default');
}
複製程式碼
Assert
- 斷言: 如果條件表示式結果不滿足需要,則可以使用
assert
語句中斷程式碼的執行 assert
方法的引數可以為任何返回布林值的表示式或者方法。- 如果返回的值為
true
,斷言執行通過,執行結束 - 如果返回值為
false
,斷言執行失敗,會丟擲一個異常 - 可在開發過程中, 監測程式碼是否有問題時使用
// Make sure the variable has a non-null value
assert(text != null);
// Make sure the value is less than 100
assert(number < 100);
// Make sure this is an https URL
assert(urlString.startsWith('https'));
複製程式碼
注意:斷言只在開發模式下執行有效,如果在生產模式 執行,則斷言不會執行
這篇文章的簡單介紹就到這裡了, 下一篇將會記錄
Dart
的基本資料型別
參考文獻
歡迎您掃一掃下面的微信公眾號,訂閱我的部落格!