目錄
- 前言
- 代碼注釋
- 變量和常量
- 數(shù)據(jù)類型
- 操作符
- 控制流
- 異常
前言
本篇開始講解Dart語法,期間會通過對比Java飒筑、kotlin片吊、Python、Groovy來區(qū)分語言直接的不同协屡。
-
行尾分號
Dart中每行代碼以分號為標(biāo)示俏脊,代表本行結(jié)束。和Java一樣肤晓,kotlin爷贫、groovy认然、Python中不需要行尾分號。
-
生產(chǎn)環(huán)境和開發(fā)環(huán)境
說下個(gè)人理解生產(chǎn)環(huán)境就是正式上線后的環(huán)境漫萄,開發(fā)環(huán)境就是開發(fā)過程中的環(huán)境季眷。有點(diǎn)類似Android中的Release模式和Debug模式。
代碼注釋
-
行注釋
和java一樣卷胯,雙引號//來注釋單行代碼
-
多行注釋
Dart中使用
/* … */
用來注釋一段代碼(可以是一行子刮,也可以是多行)。-
文檔注釋
用來對一個(gè)類或者方法進(jìn)行說明的注釋內(nèi)容窑睁。位于類之前或者方法之前挺峡。
可以使用 /// 開始, 也可以使用 /** 開始 并以 */ 結(jié)束
在文檔注釋中可以使用中括號[]來引用 classes担钮、 methods橱赠、 fields、 top-level variables箫津、 functions狭姨、 和 parameters等內(nèi)容。
變量和常量
-
變量的定義
-
var 自動(dòng)類型推斷
如這種樣式:
var name = 'Bob';
使用var來聲明一個(gè)變量苏遥,然后通過初始化賦值來自動(dòng)進(jìn)行類型推斷饼拍。 -
顯示聲明
如這種:
String name = 'Bob';
和Java一樣直接聲明變量的類型。
-
-
變量的默認(rèn)值
所有變量的默認(rèn)值都是null田炭。Dart中一切都是對象师抄,即使是數(shù)字類型,也是一個(gè)對象教硫。
示例代碼:
int lineCount; assert(lineCount == null); // 生產(chǎn)環(huán)境中asset會忽略叨吮,開發(fā)環(huán)境如果條件非true會拋異常
-
常量
在使用過程中不會被修改的變量,我們稱之為常量瞬矩。Dart中的常量分為兩種:
- final:只能被賦值一次的變量茶鉴。
- const:在編譯時(shí)就固定的常量。如果希望常量是類級別的景用,需要使用需要標(biāo)記為
static const
來修飾涵叮,類似java中的static。
定義和初始化方法:
final name = 'Bob'; // 自動(dòng)類型推斷丛肢,此時(shí)不需要var來修飾围肥; final String nickname = 'Bobby'; // 顯示聲明,直接執(zhí)行數(shù)據(jù)類型蜂怎; const bar = 1000000; const double atm = 1.01325 * bar;
數(shù)據(jù)類型
Dart中支持的數(shù)據(jù)類型穆刻,也叫內(nèi)建類型。包含:Number杠步、String氢伟、Boolean榜轿、List、Map朵锣、Set谬盐、Rune、Symbol诚些。
-
Number
Number是數(shù)字類型飞傀,又細(xì)分為int和double:
- int:整數(shù)類型。取值范圍取決于平臺诬烹,DartVM上是-2^63 到 2^63 - 1之間砸烦。如果被編譯為JS,那么取值范圍就是-2^53 到 2^53 - 1绞吁。
- double:雙精度浮點(diǎn)類型幢痘,也就是帶小數(shù)點(diǎn)的數(shù)據(jù)類型。
Number類型的初始化:
var x = 1; // 默認(rèn)十進(jìn)制 var hex = 0xDEADBEEF; // 十六進(jìn)制 var y = 1.1; // 自動(dòng)推斷為double var exponents = 1.42e5; // 科學(xué)計(jì)數(shù)法 double z = 1; // 相當(dāng)于 double z = 1.0 從Dart2.1開始直接家破,之前的版本會報(bào)錯(cuò)
Number和字符串轉(zhuǎn)換
字符串轉(zhuǎn)Number颜说,直接使用int/double中的parse函數(shù),直接傳入字符串即可
var one = int.parse('1'); // String -> int , 輸出為1 var onePointOne = double.parse('1.1'); // String -> double
Number轉(zhuǎn)字符串汰聋,直接使用toString()函數(shù)即可
String oneAsString = 1.toString(); // int轉(zhuǎn)字符串 String piAsString = 3.14159.toStringAsFixed(2); // 轉(zhuǎn)為字符串并只保留后兩位门粪,輸出為3.14
-
String字符串
創(chuàng)建字符串
可以使用單引號、雙引號马僻、三引號來定義一個(gè)字符串
單引號:使用單引號來定義一個(gè)字符串庄拇。單引號中如果需要嵌套其它引號注服,需要在引號前加
\
來進(jìn)行轉(zhuǎn)義韭邓。雙引號:和單引號類似,但雙引號中可以直接嵌套單引號溶弟,不需要轉(zhuǎn)義女淑。
-
三引號:使用三個(gè)單引號或者三個(gè)雙引號來定義一段字符串。這種字符串可以包含多行辜御。
var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";
字符串中引用變量
字符串可以通過
${
expression
}
的方式內(nèi)嵌表達(dá)式鸭你。 如果表達(dá)式是一個(gè)標(biāo)識符,則 {} 可以省略擒权。var s = 'string interpolation'; var result = '${s.toUpperCase()} is very handy!';
原始字符串
當(dāng)我們希望整個(gè)字符串中任何轉(zhuǎn)移字符都不生效袱巨,而是要保留純文本含義,那么可以在字符前加一個(gè)r標(biāo)志來表明這是一個(gè)原始字符串。類似于Python。
示例代碼:
var s = r"在Dart中使用 \n 來標(biāo)示換行"; // 這里的\n并沒有直接被轉(zhuǎn)義為換行符
字符串相等比較
使用
==
來比較兩個(gè)字符串是否相等停忿。字符串拼接
將多個(gè)字符串拼接為一個(gè)字符串切蟋,直接使用
+
來連接兩個(gè)字符串即可。 -
Boolean布爾
有兩個(gè)值
true
和false
抄淑。這兩個(gè)值也是一個(gè)對象衩婚。定義一個(gè)布爾變量使用
bool
-
List數(shù)組
定義方式
使用中括號
var list = [1, 2, 3];
注意:只能插入同類型的元素剔应,如果類型不一致會報(bào)錯(cuò)咒林。
讀取元素
使用下標(biāo)來獲取某個(gè)元素熬拒。下標(biāo)從0開始。
-
Set
一個(gè)無序不重復(fù)的序列垫竞。在Set中每個(gè)元素都是唯一的澎粟,不會出現(xiàn)重復(fù)的元素,有的話會自動(dòng)刪除欢瞪。類似Python中的元祖捌议。
定義Set
使用大括號來定義
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; var names = <String>{};; // 定義一個(gè)空字符串Set var names = {}; // 定義一個(gè)空Set
添加元素
var elements = <String>{}; elements.add('fluorine'); elements.addAll(halogens);
-
Map字典
Dart中用來存放鍵值對的一種數(shù)據(jù)類型,我們稱之為Map引有,也就是字典瓣颅。在map中一個(gè)key只能出現(xiàn)一次。當(dāng)我們從map中取元素時(shí)譬正,如果key不存在宫补,那么不會拋異常,但是會返回null曾我。key可以是字符串粉怕,也可以是純數(shù)字。
Map對象的定義和初始化
Map和Set一樣抒巢,都是使用大括號來進(jìn)行初始化賦值贫贝。區(qū)別就是Set存的是單個(gè)元素,而Map存的是鍵值對蛉谜。
var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' // 最后一個(gè)元素后稚晚,可以帶逗號,也可以不帶 }; var gifts = Map(); gifts['first'] = 'partridge'; gifts['second'] = 'turtledoves'; gifts['fifth'] = 'golden rings'; // 使用數(shù)字作為key var nobleGases = Map(); nobleGases[2] = 'helium'; nobleGases[10] = 'neon'; nobleGases[18] = 'argon';
Map對象插入值和取值
除了初始化時(shí)對map進(jìn)行賦值型诚,后續(xù)也可以直接通過key進(jìn)行賦值客燕。
var gifts = {'first': 'partridge'}; gifts['fourth'] = 'calling birds'; // 賦值 assert(gifts['first'] == 'partridge'); // 取值
Runne和Symbol,平時(shí)沒用到狰贯,用到的時(shí)候再來補(bǔ)充也搓。
操作符
操作符就是兩個(gè)對象之間相互操作的一些運(yùn)算操作,比如兩個(gè)整數(shù)相加涵紊。
操作符的優(yōu)先級:從左到右傍妒,從上到下。
-
算數(shù)運(yùn)算符
操作符 解釋 + 相加運(yùn)算摸柄, var a = 1 + 1;
– 減號 , var a = 2 - 1;
-expr 負(fù)號 * 乘號 / 相除颤练,5 / 2 的結(jié)果是 2.5 ~/ 除號,但是返回值為整數(shù)塘幅。5 / 2 的結(jié)果是 2 昔案。 % 取模尿贫,相除之后取余數(shù)。 ++var 變量自動(dòng)加一踏揣。如果前面有賦值語句庆亡,那么會先加一后賦值。 var++ 變量自動(dòng)加一捞稿。如果前面有賦值語句又谋,那么會先賦值后加一。 --var 變量自動(dòng)減一娱局。如果前面有賦值語句彰亥,那么會先減一后賦值。 var-- 變量自動(dòng)減一衰齐。如果前面有賦值語句任斋,那么會先賦值后減一。 -
關(guān)系運(yùn)算符
操作符 解釋 == 相等耻涛。判斷兩個(gè)對象x和y是否表示相同的事物废酷, 使用 ==
運(yùn)算符。!= 不等 > 大于 < 小于 >= 大于等于 <= 小于等于 -
類型運(yùn)算符
操作符 解釋 as 類型轉(zhuǎn)換抹缕。 a as b
將a轉(zhuǎn)換為b澈蟆;is 如果對象是指定的類型返回 True 。例如卓研, obj is Object
總是 trueis! 如果對象是指定的類型返回 False -
邏輯操作符
操作符 解釋 !表達(dá)式 對表達(dá)式結(jié)果取反(true 變?yōu)?false 趴俘,false 變?yōu)?true) || 邏輯 OR && 邏輯 AND -
條件表達(dá)式
if-else
表達(dá)式的兩種種簡寫方式。 三元表達(dá)式
格式為:
condition ? 表達(dá)式1 : 表達(dá)式2
如果 condition 是 true奏赘,執(zhí)行 表達(dá)式1 (并返回執(zhí)行的結(jié)果)寥闪; 否則執(zhí)行 表達(dá)式2 `并返回其結(jié)果。
二元表達(dá)式
格式如下:
expr1 ?? expr2
如果 expr1 是 non-null志珍,返回其值橙垢; 否則執(zhí)行 expr2 并返回其結(jié)果。
-
級聯(lián)操作符
級聯(lián)操作符 (..) 可以在同一個(gè)對象上 連續(xù)調(diào)用多個(gè)函數(shù)以及訪問成員變量伦糯。使用級聯(lián)操作符可以避免創(chuàng)建 臨時(shí)變量, 并且寫出來的代碼看起來 更加流暢嗽元。
示例代碼
querySelector('#confirm') // 獲取對象敛纲。 ..text = 'Confirm' // 調(diào)用成員變量。 ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); // 等同于下面的代碼 var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!')); // 嵌套使用級聯(lián)代碼 final addressBook = (AddressBookBuilder() ..name = 'jenny' ..email = 'jenny@example.com' ..phone = (PhoneNumberBuilder() ..number = '415-555-0100' ..label = 'home') .build()) .build();
控制流
Dart中的控制流分為如下幾種:if-else剂癌、for循環(huán)淤翔、while循環(huán)、switch佩谷、assert
-
if-else
和Java完全一樣旁壮,直接看demo即可:
if (isRaining()) { you.bringRainCoat(); } else if (isSnowing()) { you.wearJacket(); } else { car.putTopDown(); }
-
for循環(huán)
標(biāo)準(zhǔn)寫法
和Java完全一樣
var message = StringBuffer('Dart is fun'); for (var i = 0; i < 5; i++) { message.write('!'); }
for-in迭代寫法
var collection = [0, 1, 2]; for (var x in collection) { print(x); // 0 1 2 }
迭代器對象forEach寫法
實(shí)現(xiàn)了 Iterable 接口的對象监嗜, 可以使用 forEach()方法
candidates.forEach((candidate) => candidate.interview());
跳過循環(huán)
- break:結(jié)束循環(huán);
- continue:跳過本次循環(huán)抡谐,開始下次循環(huán)裁奇;
-
while循環(huán)
用法和Java中完全一樣
while (!isDone()) { doSomething(); } do { printLine(); } while (!atEndOfPage());
-
switch
用法和java中的用法完全一直。不過Dart中全部是使用
==
來進(jìn)行條件判斷的麦撵。示例代碼
var command = 'OPEN'; switch (command) { case 'CLOSED': case 'NOW_CLOSED': // 多個(gè)條件可以執(zhí)行同一個(gè)條件語句 executeClosed(); break; case 'OPEN': // 滿足open條件刽肠,執(zhí)行對應(yīng)代碼 executeOpen(); break; // case執(zhí)行結(jié)束要手動(dòng)調(diào)用break代碼,否則會繼續(xù)向下執(zhí)行免胃。 default: // 默認(rèn)條件 executeUnknown(); }
注意:如果沒有滿足的條件音五,且沒有defalut case,那么會拋異常羔沙。
-
斷言assert
通常在自動(dòng)化測試和單元測試的時(shí)候會使用到斷言躺涝。在Dart中, assert 語句只在開發(fā)環(huán)境中有效扼雏, 在生產(chǎn)環(huán)境是無效的诞挨。 Flutter 中的 assert 只在debug 模式中有效。
使用方法
assert的使用方法很簡單呢蛤,傳入一個(gè)條件語句:
- 如果為true就通過惶傻,程序正常運(yùn)行;
- 如果不為true其障,正常的程序執(zhí)行流程會被中斷银室。
示例代碼
// 確認(rèn)變量值小于100。 assert(number < 100);
異常
-
拋出異常
使用方法
throw new FormatException('Expected at least 1 section'); // 拋出一個(gè)格式異常 throw 'Out of llamas!'; // 拋出任意對象
胖箭頭簡寫
因?yàn)閽伋霎惓V挥幸恍欣恚钥梢允褂门旨^來簡寫
void distanceTo(Point other) => throw UnimplementedError();
-
捕獲異常 catch
示例代碼
try { breedMoreLlamas(); } on OutOfLlamasException { // 一個(gè)特殊的異常 buyMoreLlamas(); } on Exception catch (e) { // 其他任何異常 print('Unknown exception: $e'); } catch (e) { // 沒有指定的類型蜈敢,處理所有異常 print('Something really unknown: $e'); }
使用try-catch來嘗試捕獲異常;
使用on來判斷異常的類型汽抚;
多個(gè)異常就用多個(gè)on來判斷異常類型抓狭;
不加on則捕獲所有異常
-
函數(shù) catch() 可以帶有一個(gè)或者兩個(gè)參數(shù), 第一個(gè)參數(shù)為拋出的異常對象造烁, 第二個(gè)為堆棧信息 (一個(gè) StackTrace 對象)否过。
try { // ··· } on Exception catch (e) { print('Exception details:\n $e'); } catch (e, s) { print('Exception details:\n $e'); print('Stack trace:\n $s'); }
重新拋出異常
我們在catch完一個(gè)異常后,可能需要把這個(gè)異常再次拋出惭蟋∶绻穑可以使用rethrow,將之前的異常重新拋出告组。
try { dynamic foo = true; print(foo++); // Runtime error } catch (e) { print('misbehave() partially handled ${e.runtimeType}.'); rethrow; // Allow callers to see the exception. }
-
Finally
和java一樣煤伟,不管是否拋出異常, finally中的代碼都會被執(zhí)行。
- 如果
catch
沒有匹配到異常便锨, 異常會在finally執(zhí)行完成后围辙,再次被拋出; - 如果有匹配到catch,那么會等匹配的
catch
執(zhí)行完成后放案,再執(zhí)行finally姚建;
try { breedMoreLlamas(); } catch (e) { print('Error: $e'); // Handle the exception first. } finally { cleanLlamaStalls(); // Then clean up. }
- 如果