谷歌推出Flutter跨平臺UI框架後,對移動端的開發又產生了新的影響,Flutter採用Dart語言開發,而Flutter爲何選擇Dart語言做爲惟一的開發語言呢?總的來講,其擁有以下優點git
一般來講一門語言要麼使用AOT編譯,編譯慢,開發效率低,或者使用JIT編譯,在運行時編譯,雖然能夠熱重載,可是執行效率低,而Dart在這兩種之間作出了完美平衡,當開發時使用JIT編譯,調試快,所見即所得,開發效率高,當發佈時,使用AOT編譯,編譯成目標平臺的本地代碼,執行效率高。程序員
官方下載地址 共有三種SDK版本選擇github
本章僅做爲Dart編程語法學習,這裏建議安裝Server版的SDK,而後選擇Windows版本進行下載。編程
在Windows上,經過點擊下一步便可安裝,安裝完成後,需將dart-sdk
下的的bin
目錄添加到系統Path環境變量中。這一步驟是一般的命令配置步驟。數組
做爲Dart語言的學習,不建議下載笨重的IDE,官方提供支持VSCode 編輯器插件,建議使用VSCode 學習。markdown
從 官網下載 VSCode編輯器,安裝完成後,啓動VSCode並在插件商店中搜索Dart進行插件安裝。閉包
在VSCode中新建一個test.dart
文件,編寫以下代碼框架
void main(){
print("hello world!");
}
複製代碼
運行後成功在控制檯輸出hello world!
編輯器
Dart中的代碼註釋基本與Java語言相同函數
// 單行註釋
/* * 多行註釋 */
/** * 文檔註釋 */
/// 使用三個斜槓開頭
/// 這是Dart特有的文檔註釋
複製代碼
在Dart中,全部可以使用變量引用的都是對象,每一個對象都是一個類的實例。數字、函數和
null
也都是對象。全部的對象都繼承於Object類。
要注意,沒有初始化的變量默認值爲 null
。數值類型變量的默認值也是 null
。
數值類型num
有兩個具體子類,分別爲int
和double
,其中int
爲整數值,範圍是-2^53
至2^53
之間;double
則是64位的雙精度浮點數。
Dart中定義變量有兩種方式,一種是靜態類型語言經常使用的方式,顯式指定變量類型,另外一種則是動態語言的經常使用方式,不指定類型,由vm自動推斷。
// 1.經過顯式指定類型來定義變量
String name = "張三";
num age = 18;
// 2.使用關鍵字var,不指定類型
var address = "深南大道";
var id = 100;
/* 使用var定義變量,即便未顯式指定類型,一旦賦值後類型就被固定 * 所以使用var定義的變量不能改變數據類型 */
var number = 19;
// 如下代碼錯誤,沒法運行,number變量已肯定爲int類型
number = "2019";
複製代碼
如想動態改變變量的數據類型,應當使用dynamic
或Object
來定義變量。
// dynamic聲明變量
dynamic var1 = "hello";
var1 = 19;
print(var1); // 19
// Object聲明變量
Object var2 = 20;
var2 = "Alice";
print(var2); // Alice
複製代碼
建議在編寫代碼時,儘量顯式指定變量類型,這樣能夠提高代碼可讀性與調試的便利性。
Dart中定義常量也有兩種方式,一種使用final
關鍵字,同Java中的用法, 一個 final 變量只能賦值一次;另外一種是Dart的方式,使用const
關鍵字定義。
// 1.使用final關鍵字定義常量
final height = 10;
// 2.使用const關鍵字定義常量
const pi = 3.14;
複製代碼
須要注意,final
定義的常量是運行時常量,而const
常量則是編譯時常量,也就是說final
定義常量時,其值能夠是一個變量,而const
定義的常量,其值必須是一個字面常量值。
final time = new DateTime.now(); // 正確
const time = new DateTime.now(); // 錯誤
const list = const[1,2,3]; // 正確
const list = [1,2,3]; // 錯誤
複製代碼
// String 轉 int
var one = int.parse('1');
// String 轉 double
var onePointOne = double.parse('1.1');
// int 轉 String
String oneAsStr = 1.toString();
// double 轉 String
String piAsStr = 3.14159.toStringAsFixed(2); // 保留兩位 '3.14'
// Dart也支持整數位操做,<<、 >>、&、|
print((3 << 1) == 6); // 0011 << 1 == 0110
print((3 >> 1) == 1); // 0011 >> 1 == 0001
print((3 | 4) == 7); // 0011 | 0100 == 0111
複製代碼
值得一提的是,Dart中提供的字符串
插值表達式
使字符串格式化變得異常方便。
// 1.Dart可使用單引號或雙引號來建立字符串
var s1 = "hello";
var s2 = 'world';
// 2.相似Python,Dart可使用三引號來建立包含多行的字符串
var multiLine1 = """你能夠像這樣,建立一個 包含了多行的字符串內容 """;
var multiLine2 = '''你也可使用三個單引號,建立一個 包含了多行的字符串內容 ''';
// 3.相似Python,還能夠在字符串字面值的前面加上`r`來建立原始字符串,則該字符串中特殊字符能夠不用轉義
var path = r'D:\workspace\code';
// 4.Dart支持使用"+"操做符拼接字符串
var greet = "hello" + " world";
// 5.Dart提供了插值表達式"${}",也能夠用於拼接字符串
var name = "王五";
var aStr = "hello,${name}";
print(aStr); // hello,王五
// 當僅取變量值時,能夠省略花括號
var aStr2 = "hello,$name"; // hello,王五
// 當拼接的是一個表達式時,則不能省略花括號
var str1 = "link";
var str2 = "click ${str1.toUpperCase()}";
print(str2); // click LINK
// 6. 與Java不一樣,Dart使用"=="來比較字符串的內容
print("hello" == "world");
複製代碼
Dart中的布爾類型用法同Java,僅有
false
、true
兩個值,不能使用0、非0或者null
、非null
來表達false
和true
。與Java不一樣的是,布爾類型的默認值爲null
bool flags;
print(flags); // null
複製代碼
Dart中列表操做與JavaScript中的數組類似。
// 建立列表
var list = [1, 2, 3];
// 下標從0開始。使用length能夠訪問list的長度
print(list[0]);
print(list.length);
// 可使用add添加元素
list.add(5);
// 可在list字面量前添加const關鍵字,定義一個不可改變的 列表(編譯時常量)
var constantList = const [1, 2, 3];
constantList[1] = 1; // 報錯
複製代碼
又稱爲關聯數組,至關於Java中的HashMap
// 1.經過字面量建立Map
var gifts = {
'first' : 'partridge',
'second': 'turtledoves',
'fifth' : 'golden rings'
};
// 2.使用Map類的構造函數建立對象
var pic = new Map();
// 往Map中添加鍵值對
pic['first'] = 'partridge';
pic['second'] = 'turtledoves';
pic['fifth'] = 'golden rings';
// 3.獲取Map的長度
print(pic.length);
// 4.查找Map
pirnt(pic["first"]);
print(pic["four"]); // 鍵不存在則返回 null
複製代碼
在Dart中,函數(或方法) 也是對象,它的類型是
Function
。 這意味着,函數能夠賦值給變量,也能夠當作其餘函數的參數。
Dart中定義函數,基本上與Java相似
String greet(String name){
return "hello,$name";
}
複製代碼
在Dart中,類型是可選,能夠省略顯式的類型,但仍然建議顯式指定類型。
greet(name){
return "hello,$name";
}
複製代碼
要注意,函數也是對象,全部函數都有返回值。當沒有指定返回值的時候,函數會返回null
。固然,若是你強行使用void
來修飾函數,則函數真的沒有返回值,這種狀況就另當別論了。
Dart中支持兩種可選參數
在Java中一般使用方法重載來實現同名方法的不一樣參數調用,Dart中則能夠經過可選參數來實現相同效果。
先來看一下命名參數
,它使用花括號來定義參數列表
// 定義一個函數,參數列表用花括號包裹
enableFlags({bool bold, bool hidden}) {
// do something
}
// 調用方式,傳參時使用"參數名:值"的形式
enableFlags(hidden:true,bold:false);
複製代碼
若是在定義函數時,給參數列表中的參數設置默認值,則該參數就是可選的,函數調用時能夠忽略該參數,使用默認的值。
// 定義add函數
add({int x, int y=1, int z=0}){
print(x + y + z;
}
// 調用
add(x:18); // 19
add(x:18, y:2, z:10); // 30
複製代碼
這裏須要注意一下,SDK 1.21以前的版本中,命名參數不能使用=
號來設置默認值,而SDK 1.21以後,只能使用=
號來設置默認值。所以,請檢查並升級SDK版本。
位置可選參數
使用中括號來定義參數列表,中括號中的參數是可選的
// 定義add函數
add(int x, [int y, int z]){
int result = x;
if (y != null){
result = result + y;
}
if (z != null){
result = result + z;
}
print(result);
}
// 調用
add(18); // 18
add(18,12); // 30
add(18, 12, 15); // 45
複製代碼
給位置可選參數
設置默認值
// 定義add函數
add(int x, [int y=0, int z=0]){
print(x +y+z);
}
複製代碼
最後須要注意一下命名可選參數
與位置可選參數
的區別,前者中的參數與順序無關,無需按順序傳參,且傳參數時需使用冒號;後者與順序相關,傳參必須依照順序。
大部分函數都有名字,但咱們也能夠建立沒有名字的函數,稱爲匿名函數,也被稱爲lambda表達式或者閉包。
// 定義匿名函數,並將其賦值給一個變量func,注意,函數體最後的花括號處必須有分號結束。
var func = (x,y){
return x + y;
};
print(func(10,11)); // 21
複製代碼
注意,匿名函數與普通函數基本相同,也有參數列表,函數體,只是省去了函數名而已。
Dart中的箭頭函數與JavaScript中的基本相同。當函數體中只包含一個語句時,咱們就可使用
=>
箭頭語法進行縮寫。注意,箭頭函數僅僅只是一個簡潔表達的語法糖。
普通函數
add(num x, num y){
return x + y;
}
print(add(18,12)); // 30
複製代碼
箭頭函數
// 與上面的普通函數徹底等價
add(num x, num y) => x + y;
print(add(18,12)); // 30
複製代碼
箭頭函數省略了花括號的表達,箭頭後面跟一個表達式,函數的返回值也就是這個表達式的值。另外,箭頭函數也能夠與匿名函數結合,造成匿名箭頭函數。
var func = (num x, num y) => x + y;
複製代碼
Dart語言中的運算符與Java中的絕大多數相同。
+
、-
、*
、/
、%
同Java語言
Dart中又多出了一個整除運算符~/
,與普通除號的區別是將相除後的結果取整返回。
如下是Dart增長的類型相關的運算符。
操做符 | 解釋 |
---|---|
as |
用於類型轉換 |
is |
若是對象是指定的類型就返回 True |
is! |
若是對象不是指定的類型返回 True |
當 obj
實現了 T
的接口時, obj is T
纔是 true。相似於Java中的instanceof
。
Dart中使用 as
操做符把對象轉換爲特定的類型,如沒法轉換則會拋出異常,所以在轉換前最好使用is
運算符進行檢測。
// 將p轉換爲Person類型再操做
(p as Person).name = 'Bruce';
複製代碼
Dart中也支持三目表達式 condition ? expr1 : expr2
除此外,Dart還增長了非空條件判斷符??
expr1 ?? expr2
上述運算表示,若是expr1的值不等於null
,則返回其值; 不然執行表達式expr2並返回其結果。
var str1 = "Hello";
var str2 = "world";
var result = str1 ?? str2.toUpperCase();
複製代碼
咱們一般使用
.
操做符調用對象的方法,這在Dart中也是支持的,可是Dart另外增長了一種級聯運算符..
,用兩個點表示。
級聯運算符
能夠在同一個對象上連續調用多個方法以及訪問成員變量。 使用它能夠避免建立臨時變量, 寫出更流暢的代碼。
假如類Person有三個方法,setName
、setAge
、save
,則可以下調用
new Person()..setName("Bob")..setAge(20)..save();
複製代碼
使用級聯運算符
調用方法,無需該方法返回對象自己便可連續的流式的調用該對象的其餘方法。
在Java中很容易碰到惱人的空指針錯誤,所以在方法調用前須要進行對象的非空判斷,這樣的判斷語句使代碼變得冗長,可讀性差,不整潔。Dart中則發明了一個新的運算符用於處理此類狀況。
條件成員訪問符?.
,它和.
相似,可是運算符左邊的對象不能爲null
,不然返回null
,若對象不爲null
,則返回對象自己。
// list1默認值爲null
List list1;
print(list1?.length); // null
List list2 = [];
print(list2?.length); // 0
複製代碼
Dart中的條件分支基本與Java相同
if
條件分支
if(i < 0){
print('i < 0');
}else if(i == 0){
print('i = 0');
} else {
print('i > 0');
}
複製代碼
switch
條件分支
// 在switch的case中可使用整數、字符串、枚舉類型和編譯時常量
String command = 'OPEN';
switch (command) {
case 'CLOSED':
break;
case 'OPEN':
break;
default:
print('Default');
}
複製代碼
Dart中的基本循環語句與Java相同
// for循環
for(int i = 0; i < 9; i++) {
print(i);
}
// while循環
while(true){
//do something
}
// do-while循環
do{
//do something
} while(true);
複製代碼
var myList = ['Java','JavaScript','Dart'];
// for...in...循環,相似Java中的加強for
for (var it in myList ){
print(it);
}
// forEach循環。其參數爲一個Function對象,這裏傳入一個匿名函數
myList.forEach((var it){
print(it);
});
// 可使用匿名箭頭函數簡寫
myList.forEach((it) => print(it));
複製代碼
使用循環遍歷Map
var myMap = {
'zhangsan':'201901',
'lisi':'201902',
'wangwu':'201902'
};
// forEach遍歷Map
myMap.forEach((k, v) => print("$k : $v"));
// 根據鍵獲取值來遍歷。經過keys返回Map中全部鍵的集合
for(var k in myMap.keys){
print("$k : ${myMap[k]}");
}
複製代碼
GitHub
關注個人公衆號:編程之路從0到1