本文收錄于dart入門潛修系列教程糜值。
創(chuàng)作不易塞琼,轉(zhuǎn)載還請備注赠叼。
前言
本篇文章會對dart語言的基本語法和內(nèi)置類型做一個整體的闡述扒袖。
變量
dart為變量提供一個關(guān)鍵字var,這與js歼培、kotlin等都很像震蒋,var只是聲明一個變量,至于這個變量是個什么類型則由“類型關(guān)鍵字”來決定躲庄,如下所示:
//定義了一個變量var1,此時沒有指定var1的類型查剖,
//則由dart編譯器自動推斷:即var1是個字符串
var var1 = "test";
//顯示指定變量str的類型為String
String str = "test";
在dart中一切都是對象(包括下面提到的內(nèi)置類型)。因此噪窘,var var1 = "test"這句語句梗搅,實際上表達的意思是:有一個字符串對象test,其地址保存在了var1變量中。即var1實際上保存的是對象的引用地址无切,而不是對象本身荡短,這點與很多面向?qū)ο蟮恼Z言一致。
既然dart中一切都是對象哆键,那么如果我們在定義的時候沒有對其進行初始化掘托,那么其默認值是什么?這個有朋友很容易推斷出來籍嘹,在其他語言中闪盔,對象的默認值顯然是null!確實如此辱士,dart中的變量默認值就是null泪掀,但是需要特別注意的是,其內(nèi)置的諸如數(shù)字類型颂碘、布爾類型等的默認值同樣是null异赫,因為他們也是對象,如下所示:
void main() {
int i;
print(i);//打印'null'
bool j;
print(j);//打印'null'
}
在當前其他一些主流的語言中(比如java)头岔,內(nèi)置的int塔拳、bool類型默認值是永遠不可能為null的,所以如果之前學習的是java這類的語言峡竣,要特別注意這一點靠抑。
常量
除了變量外,dart還支持常量适掰,dart中修飾常量同樣有兩個關(guān)鍵字:final和const颂碧。final變量只能被賦值一次,表示運行時常量类浪,而const修飾的變量則表示是編譯時常量载城,關(guān)于運行時常量和編譯時常量,在我的另一個系列文章----->kotlin系列文章中的kotlin入門潛修之類和對象篇—屬性和字段這篇文章中有過詳細闡述(編譯時常量章節(jié))戚宦。這里再說下二者的區(qū)別:編譯時常量个曙,顧名思義锈嫩,就是在編譯的時候就可以確定的常量受楼,即編譯器編譯成可執(zhí)行文件的時候就已經(jīng)保存了該常量值;而運行時常量則只能在運行的時候才可以獲取其對應(yīng)的常量值呼寸,編譯器編譯時只保證代碼中沒有其他地方可再次修改其值艳汽,這也是為啥被稱為常量的原因。
dart中編譯時常量和運行時常量示例如下所示:
void main() {
final str = "hello word";//運行時常量
const str2 = "hello word";//編譯時常量
final String str3 = "hello word";//運行時常量对雪,顯示指定str3的類型
}
上面三個都是"常量",均無法再次進行賦值河狐。在dart中,const實際上是隱含包含有final修飾符的,即const修飾的的常量一定是final的馋艺。
再來看個關(guān)于常量的例子栅干,如下所示:
var arr = const [];
arr = [1, 2, 3];//示例1,正確
final arr1 = const [];
arr1 = [1, 2, 4];//示例2捐祠,錯誤碱鳞,無法再被賦值
const arr2 = [];
arr2 = [1, 3, 4];//示例3,錯誤踱蛀,無法再被賦值
首先需要注意區(qū)分示例1和示例2的區(qū)別窿给,示例1表示arr是個變量,其指向了一個包含編譯時常量元素的引用地址率拒,即arr本身并不是常量崩泡,只是其包含的元素是常量,所以我們可以對其進行二次賦值猬膨;示例2是錯誤的角撞,因為arr1是final的,無法再進行賦值寥掐;示例3的錯誤更是顯而易見的靴寂,使用const修飾的也無法被賦值。
了解過dart中的變量召耘、常量的定義之后百炬,下面來看下kotlin中內(nèi)置的基本數(shù)據(jù)類型。
內(nèi)置類型
numbers(數(shù)字類型)
不像其他語言污它,dart的數(shù)字類型只有兩種剖踊,一種是整型,使用int關(guān)鍵字修飾衫贬;一種是浮點型德澈,使用double關(guān)鍵字修飾。
其中int類型的最大長度是64位固惯,但這個會依賴于具體的平臺梆造,因為dart支持多種平臺,比如在dart 虛擬機上葬毫,int的表示范圍是-263 to 263 - 1镇辉,而當dart被編譯為javascript的時候其表示范圍為-253 to 253 - 1。
double類型最大長度也是64位贴捡,遵循IEEE 754標準忽肛。int和double都是num類型的子類,num定義了一些基本的運算操作烂斋,比如加減乘除等屹逛,dart中數(shù)字的使用示例如下所示:
void main() {
int i = 1;//定義一個整型變量i
double j = 2.1;//定義一個小數(shù)j
num result = i + j;//定義了一個num類型的result
print(result);//打印3.1
}
上面代碼演示了數(shù)字類型的使用础废,其中在第三行中,我們使用num來接收i+j的結(jié)果罕模,這是允許的评腺,因為前面說過num是int和double的父類,這是面向?qū)ο笳Z言的基本特點淑掌。下面來看下int和double類的聲明歇僧,如下所示:
//整型int類的定義
abstract class int extends num {...}
//double類型的定義
abstract class double extends num {...}
//這就是num的定義
abstract class num implements Comparable<num> {
bool operator ==(Object other);
num operator +(num other);
num operator -(num other);
int operator <<(int shiftAmount);
//省略內(nèi)容...
}
上面代碼展示了數(shù)字類型的相關(guān)定義,也驗證了我們前面的說法锋拖。從定義也可以看出诈悍,數(shù)字類型的默認值為什么為null,因為他們都是class類型兽埃,對應(yīng)的實例變量如果沒有被賦值侥钳,其默認值就是null。
實際上柄错,數(shù)字類型除了提供了這些簡便的操作符外舷夺,還提供了一些便利的方法,如求絕對值售貌、取整等方法给猾,來看幾個示例:
void main() {
int i = -1; //定義一個整型變量i
double j = 2.1; //定義一個小數(shù)j
print(i.abs());//求i的絕對值,打印 ‘1’
print(j.ceil());//求j的向上最大整數(shù)颂跨,打印'3'
print(j.floor());//求j的向下的最大整數(shù)敢伸,打印'2'
print(j.round());//求離j最近的整數(shù),四舍五入恒削,打印'2'
print(j.truncate());//截取掉小數(shù)點取整池颈,打印'2'
j = 2.6;//驗證小數(shù)位超過0.5的情形
print(j.round());//求離j最近的整數(shù),四舍五入钓丰,打印'3'
print(j.truncate());//截取掉小數(shù)點取整躯砰,打印'2'
print(j.clamp(1,3));//如果j再1-3之間則返回j,否則返回離其最近的邊界值携丁,這里打印j的值 ‘2.6’
print(j.clamp(3,4));//打印‘3’琢歇,原理同上
print(j.clamp(1,2));//打印‘2’,原理同上
}
booleans
dart中為布爾值提供了bool關(guān)鍵字梦鉴,所謂布爾值就是非真既假的表達李茫。在dart中使用bool還是需要稍加注意的,看個例子:
void main() {
bool isOk;
print(isOk ? "is ok" : "is not ok");//!!!編譯錯誤
}
是的尚揣,上面代碼會編譯錯誤涌矢!原因是isOk沒有被賦值掖举,其默認值為null快骗,而null不能作為bool表達式,所以在使用bool值之前一定要進行初始化,如下所示:
void main() {
bool isOk = true;
print(isOk ? "is ok" : "is not ok");//打印'is ok'
}
其實null在dart中是所有變量的“通病”方篮,因為dart中一切都是對象名秀,所以在做邏輯之前,一定要考慮變量值可能為null的情況藕溅。
dart中的布爾值只有兩個對象值:true和false匕得,這兩個布爾值實際上是個編譯常量。在dart中巾表,除了bool類型之外汁掠,其他類型都無法用在if表達式和assert方法中,如下所示:
var str = '';
if (str) {//錯誤集币,str是個字符串類型考阱,無法用于if表達式
}
if(str != null){//正確,str != null返回了bool值
}
Strings
dart中的字符串是用utf-16編碼的字符序列鞠苟。在dart中乞榨,創(chuàng)建字符串有兩種方法:使用雙引號和單引號,如下所示:
void main() {
var str1 = "hello word";//定義了一個字符串str1
var str2 = 'hello word';//定義了一個字符串str2
var str1AndStr2 = str1 + str2;//可以使用+號操作符当娱,拼接兩個字符串
var newStr1 = "new str1 say: " + str1;//同上
var newStr2 = "new str2 say: $str2";//也可以使用$獲取字符串變量的值
var str3 = "`hello world'\"";//使用\轉(zhuǎn)義特殊字符串
//dart同樣提供了這種拼接形式吃既,此時將會忽略字符串之外的
//換行和空格,此處打印 Hello world end...
var concatenateStr = 'Hello '
'world'
" end...";
//三引號表示保持書寫的格式進行打印跨细,即寫的是什么格式就打印什么格式鹦倚。
var concatenateStr2 = '''Hello
world
end..''';
print(concatenateStr2);
}
lists (列表或者數(shù)組)
幾乎所有語言都有數(shù)組,表示有序的數(shù)據(jù)集合冀惭。除了數(shù)組之外申鱼,很多語言還提供了列表(list),列表底層有多種實現(xiàn)方式云头,數(shù)組就是其底層實現(xiàn)的常見方式之一捐友。在dart中,數(shù)組就是包含對象的列表溃槐,因此他們統(tǒng)稱為lists匣砖。換句話說,當提到dart中的lists時昏滴,其實就是數(shù)組的概念猴鲫。
列表的示例如下所示:
void main() {
var list = [1, 2, 3];//定義了一個數(shù)據(jù)集合list
list[0] = 100;//可以通過下標進行賦值
for (int i = 0; i < list.length; i++) {//打印list中的各個元素
print(list[i]);
}
//定義了一個包含有編譯時常量的列表list2
var list2 = const[1, 2, 3];
list2[0] = 200;//!!!編譯錯誤,編譯時常量無法被重新賦值
}
上面list的寫法是字面量寫法谣殊,我們還可以通過dart提供的List類型來完成上述功能拂共,如下所示:
var list = List();//生成一個List類型的對象
list.add(1);//添加元素1
list.add(2);//添加元素2
print(list);//打印 ‘ [1, 2] ’
上面兩種不同的寫法,實際上生成的都是一個類型的集合:List<int>姻几,即只能向集合中存入int類型的元素宜狐,這里涉及到泛型的概念势告,將會在后續(xù)文章中闡述。
maps(映射)
所謂映射就是提供key-value的一個數(shù)據(jù)存儲結(jié)構(gòu)抚恒。在dart中key和value可以是任何類型咱台,但是key不能重復,而value可以重復俭驮。生成map對象同樣有兩種方式回溺,一種是通過字面量的形式,一種是使用Map類型混萝,示例如下:
void main() {
var map = {//通過字面量定義了一個map對象
"key1":"hello",
"key2":"world"
};
print(map["key1"]);//打印key1對應(yīng)的值
var map2 = Map();//通過Map類型遗遵,生成一個對象
map2["key1"] = "map2 value";//添加 key1 : map2 value映射
map2[1] = "map2 value2";//添加 1 : map2 value映射
print(map2);//打印{key1: map2 value, 1: map2 value2}
}
runes
dart提供了一些可以使用utf-32編碼表示的特殊字符,這些字符會被渲染成各種各樣的可視化符號逸嘀,比如我們常見的表情符瓮恭、icon標識等,這就是所謂的runes(即神秘意義的符號)厘熟,舉個例子就很容易理解了:
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
上面代碼執(zhí)行后打印如下:
? ?? ?? ?? ?? ??
dart中還有一個Symbol類型屯蹦,使用#修飾(如#test),其字面量是一個編譯時常量绳姨,但是實際中基本用不到登澜,所以不再闡述。
至此飘庄,dart的基本語法和內(nèi)置類型闡述完畢脑蠕。