Dart 語法學(xué)習(xí)目錄
第一節(jié): Dart 語法了解,認識變量,常量,數(shù)據(jù)類型
第二節(jié): Dart 操作符(運算符)
第三節(jié): Dart 中常用集合 List/Map
第四節(jié): Dart 函數(shù)使用,聲明函數(shù)/匿名函數(shù)/可選參數(shù)/作用域/閉包
第五節(jié): Dart 面向?qū)ο?構(gòu)造函數(shù)/靜態(tài)屬性
第六節(jié): Dart中抽象類abstract/接口implements/混入Mixin
第七節(jié): Dart中泛型/泛型定義與使用
第八節(jié): Dart 中的庫/自定義庫/內(nèi)置庫/第三方庫
1. dart的基本用法了解
1.1 dart入口函數(shù)與輸出
dart運行需要一個入口函數(shù)為main,
通過下面的示例,先簡單了解dart基本使用
在dart語法中輸出控制臺為print() 方法
// 有返回值的dart
main(){
// 打印
print("hello dart")
}
結(jié)果會在控制臺輸出hello dart
我們也可以將main 入口函數(shù)定義為沒有返回值的函數(shù),
// 沒有返回指定入口
void main(){
print("你好 dart")
}
void 是限定函數(shù)的返回來寫為空
1.2 dart語言中的注釋
// 單行注釋
/// 單行注釋
/*
多行注釋
*/
2. Dart 語言重要概念的理解
- 任何保存在變量中的都是一個 對象 , 并且所有的對象都是對應(yīng)一個 類 的實例。 無論是數(shù)字,函數(shù)和
null都是對象。所有對象繼承自Object類。 - 盡管 Dart 是強類型的,但是 Dart 可以推斷類型,所以類型注釋是可選的。
- Dart 支持泛型,如
List <int>(整數(shù)列表)或List <dynamic>(任何類型的對象列表) - Dart 支持頂級函數(shù)(例如
main()), 同樣函數(shù)綁定在類或?qū)ο笊希ǚ謩e是 靜態(tài)函數(shù) 和 實例函數(shù) )。 以及支持函數(shù)內(nèi)創(chuàng)建函數(shù) ( 嵌套 或 局部函數(shù) ) 。 - Dart 支持頂級 變量 , 同樣變量綁定在類或?qū)ο笊希o態(tài)變量和實例變量)。 實例變量有時稱為字段或?qū)傩浴?/li>
- 與 Java 不同,Dart 沒有關(guān)鍵字 “public” , “protected” 和 “private” 。 如果標識符以下劃線(_)開頭,則它相對于庫是私有的。
- 標識符 以字母或下劃線(_)開頭,后跟任意字母和數(shù)字組合。
- Dart 語法中包含 表達式( expressions )(有運行時值)和 語句( statements )(沒有運行時值)。 例如,條件表達式
condition ? expr1 : expr2的值可能是expr1或expr2。 將其與if-else語句相比較,if-else 語句沒有值。 一條語句通常包含一個或多個表達式,相反表達式不能直接包含語句。 - Dart 工具提示兩種類型問題:警告和錯誤。 警告只是表明代碼可能無法正常工作,但不會阻止程序的執(zhí)行。 錯誤可能是編譯時錯誤或者運行時錯誤。 編譯時錯誤會阻止代碼的執(zhí)行; 運行時錯誤會導(dǎo)致代碼在執(zhí)行過程中引發(fā) [異常]
這些重要的概念先有第一定的了解,讀一讀, 不理解什么意思沒有關(guān)系,繼續(xù)往后學(xué),等學(xué)完dart以后在會來來理解這些概念
3. Dart語言中的關(guān)鍵字
關(guān)鍵字先看一眼,混個眼熟, 不用刻意的去背,隨著學(xué)習(xí)的深入,大部分關(guān)鍵詞都會接觸到,或者在自己的代碼示例中出現(xiàn),用多了就熟了
關(guān)鍵字就不在這里羅列了, 了解請移步官網(wǎng)關(guān)鍵字
4. dart中的變量
4.1 dart 標識符命名規(guī)則
- 變量的名稱必須有數(shù)字,字母,下劃線和美元符($)組成
- 標識符不能以數(shù)字開頭
- 標識符不能是保留字或關(guān)鍵字
- 變量的名稱是區(qū)分大小寫的, 如果,age和 Age不是同一個變量
- 標識符(變量)一定要見名知意,
4.2 變量定義
使用
var聲明變量,此時沒有明確類型,編譯的時候根據(jù)值明確類型dart變量定義時可以明確類型,來幫助 Dart 去捕獲異常以及 讓代碼運行的更高效
變量定義為初始化賦值,變量默認值為null
如果對象不限于單一類型(沒有明確的類型),請使用Object或dynamic關(guān)鍵字
根據(jù)上面變量定義的描述,我們來好好通過示例來看看變量定義的描述
4.2.1 不明確類型的定義變量
是有var定義變量,不明確變量的類型,dart自己會有類型檢查, 會根據(jù)var關(guān)鍵字在定義變量時所賦予的初值的類型明確變量的類型
void main(){
// 定義變量
// var 定義變量, 值是什么類型,變量就是什么類型
var str = "hello wrod";
var num = 1234;
// 打印變量
print(str);
print(num);
// 判斷str num 變量的類型
print(str is String); // true
print(num is int); // true
}
通過示例的打印結(jié)果,我們知道了str和num兩個變量的數(shù)據(jù)類型
所以var 定義變量的類型是根據(jù)第一次賦值變量的時候推到出來的類型, 也就是說在賦予初始值的時候,變量的類型就已經(jīng)確定了,
那么問題來了,類型確定了之后的變量還能賦予其他類型的值嗎?
看示例:
void main(){
var str2 = '';
strs = 123;
print(str2);
}
// 這樣寫就會報錯, str2 是字符串類型, 賦值數(shù)字報錯
我們發(fā)現(xiàn)一旦變量類型確定在賦值其他類型的變量就會報錯.
但是如果通過var 定義變量 并沒有賦初值, 那么這個變量不就沒辦法確定類型
那么此時的類型應(yīng)該還是默認的類型Null,這樣的話,我們是否可以自由給變量賦予任何數(shù)據(jù)類型的值呢
所有后面可以自由賦值任何數(shù)據(jù)類型的值,并且可以更改, 當然不建議這么使用
void main(){
var num;
// var 定義變量沒有賦予初始值, 類型為Null
print(num is Null); // true
num = 123;
print(num); // 123
// 當重新給變量賦值時,類型也會發(fā)生變化
print(num is int); // true
print(num is Null); // false
num = "str";
print(num); // 'str'
// 還可以自由賦予不同數(shù)據(jù)類型的值
print(num is String); // true
print(num is Null); // false
}
示例中的代碼不會報錯, 可以正常輸出結(jié)果.這樣我們就了解了
在Dart中,如果使用var關(guān)鍵詞定義變量但是沒有賦予初始,就好像dart沒法限定變量為某一種類型,此時就會像JavaScript變量一樣, 可以賦予任何數(shù)據(jù)類型的值, 而此時變量的類型將有賦予的值的類型來決定
注意:
使用var定義變量但未賦予初始值. 那么變量的值為null,類型為Null
void main(){
var num;
print(num == null); // true
print(num is Null); // true
}
總結(jié):
4.2.2 通過指定類型定義變量
當然了dart也可以在定義變量時限定變量的類型,變量的類型一但被限定, 將不能給變量賦予不同類型的值
示例:
void main(){
// 定義變量
// 確定str的類型是字符串類型的變量, str只能賦值字符串,如果賦值其他類型值將會報錯
String str = "hello wrod";
// 限定變量num是數(shù)字類型
int num = 1234;
// 打印變量
print(str);
print(num);
}
注意, var 定義變量時,var 后面就不要在寫類型了, 限定了變量類型就不要在使用var了
現(xiàn)在我們對于數(shù)據(jù)類型還不是特別了解,先認識一下示例中所有的數(shù)據(jù)類型,后面會詳細探討.
4.3 動態(tài)類型dynamic
沒有指定類型的變量的類型為 dynamic,
void main(){
dynamic num = 123;
print(num);
num = '456';
print(num);
print(num is dynamic); // true
print(num is String); // true
}
此時并未指定num變量的類型,類型是有值推導(dǎo)出來的, 所以我們在判斷num類型的時候,dynamic和String都為true
dynamic 一般在使用泛型時使用
示例:
void main(){
var list = new List<dynamic>(); //泛型,會在后面總結(jié)
list.add("hello");
list.add(123);
print(list); // [hello, 123]
}
此時表示集合list里可以放任意數(shù)據(jù)類型的值
泛型是什么?先不用在意,我們會進行總結(jié)
5. Dart 中定義常量
5.1 常量定義的基本用法
dart中使用final 和const 關(guān)鍵字定義常量
對于Dart定義常量的了解
- 被
final和const修飾的變量只能賦值一次,不可更改變量值(定義常量) - 一個 final 變量只能被初始化一次; const變量是一個編譯時常量,(Const變量是隱式的final),如果 const 常量在類中,請定義為 static const。
- 被final或者const修飾的變量,變量類型可以省略,建議指定數(shù)據(jù)類型。
- 使用關(guān)鍵字定義常量時必須在第一次聲明的時候就需要初始化,否則會提示錯誤:
5.1.1 定義常量
常量就是定義之后,不能再修改值的變量.
void main(){
// 定義常量
// const 定義常量
const str = "不可修改的值";
print(str); // 不可修改的值
// final 定義常量
final num = 123;
print(num); //123
}
示例中,可以正常打印出數(shù)值, 但是這些常量已經(jīng)固定, 如果改變這些常量的值,就會報錯
如下錯誤的寫法
void main(){
// 定義常量
const str = "不可修改的值";
print(str);
str = '錯誤的'; // 會報錯,常量不可修改
print(str);
}
通過示例,我們發(fā)現(xiàn)常量就算你修改為一樣類型的數(shù)值也會報錯
5.1.2 指定常量類
final和const 定義常量,其實就是定義變量,這兩個關(guān)鍵字在修飾變量是,不允許變量被重新賦值而已, 這兩個關(guān)鍵字在修飾常量時,可以省略數(shù)據(jù)類型,
如果在final和const修飾常量時沒有指定類型,那么變量的類型將有初始賦值的類型決定.
示例:
定義常量時不限定類型
void main(){
// 定義常量
// const 定義常量
const str = "不可修改的值";
print(str); // 不可修改的值
print(str is String); // true
// final 定義常量
final num = 123;
print(num); //123
print(num is int); // true
}
通過示例,發(fā)現(xiàn)定義的常量類型就是賦值的數(shù)據(jù)類型
定義變量時限定類型
void main(){
// 定義常量 限定類型
// 在修飾常量的關(guān)鍵字和變量之前添加修飾變量的類型
// const 定義常量
const String str = "不可修改的值";
print(str); // 不可修改的值
print(str is String); // true
// final 定義常量
final int num = 123;
print(num); //123
print(num is int); // true
}
我們發(fā)現(xiàn)提前修飾變量的類型也沒有任何問題
如果你修改時的變量類型和賦值的類型不一致就會報錯
void main(){
// 定義常量 限定類型
// 在修飾變量的類型和賦值的類型不一致
// const 定義常量
const int str = "不可修改的值";
print(str);
print(str is String);
}
此時不會打印任何內(nèi)容,會直接報錯,因為修飾str變量的類型是int,可是賦予的值的類型是String,所以會直接報錯
5.1.3 聲明常量初始化賦值,
聲明常量時必須在初始化賦值, 否則就會報錯
void main(){
// 定義常量 聲明時必須初始化賦值
// const 定義常量
// const str ;
// str = "不可修改的值"
final num;
num = 20;
}
無論final還是const在聲明時未初始化賦值都會報錯;
5.2 const 和final 定義常量的區(qū)別
5.2.1 常量固定下來的時間不同
Const 變量在編譯時就已經(jīng)固定,最高級 final 變量或類變量在第一次使用時被初始化。
final不僅有const 的編譯時常量的特性,最重要的是他運行時常量, final是惰性初始化, 即在運行時第一次使用前才初始化;
void main(){
// 因為 const 聲明常量時 在定義時就初始化,所以這么寫是錯誤的
// 所以在const 聲明變量在編譯時就已經(jīng)固定了,所以此時賦予的是不能是表達式,而應(yīng)該是一個確定的值.
// 所以如下寫法是會報錯了\
// 寫法一: 實例化
// const aa = new DateTime.now();
// 寫法二:計算
// var num = 10;
// const aa = 123 * num;
// print(aa);
// final 是在第一次使用前才初始化
// 所以在聲明常量賦值是并沒有固定下來,因此初始賦值可以為表達式
// 下面兩種寫法完全沒問題
// 寫法一: 實例化
// final aa = new DateTime.now();
// 寫法二: 計算
var num = 10;
final aa = 123 * num;
print(aa);
}
5.2.2 修飾類的實例
注意修飾類實例的變量可以是final類型 ,但不能是const類型
class Person{
// 類屬性
String name = '你好';
// 類方法
getInfo(){
print(name);
}
}
void main(){
// 類實例化
// final 修飾類實例化變量
final person = new Person();
person.getInfo(); // 你好
// const就是就會報錯
// const person = new Person(); // 報錯
}
因為const是在聲明時固定的,所以不能用來修飾類實例化的常量
5.2.3 修飾變量值
任何一個變量都可以擁有一個常量的值
const關(guān)鍵字不只是聲明常數(shù)變量,您也可以使用它來創(chuàng)建常量值,以及聲明創(chuàng)建常量值的構(gòu)造函數(shù),任何變量都可以有一個常量值。
例如:
void main(){
var foo = [1,2,3];
foo.add(6);
print(foo); // [1, 2, 3, 6]
}
這樣改變值 沒有任何關(guān)系
但是如果把值限定為常量就會報錯
void main(){
var foo = const [1,2,3];
foo.add(6);
print(foo); // Cannot add to an unmodifiable list
}
因為此時被const修飾的集合[1,2,3]是常量值,不能修改.
但是要注意的是盡管你是用了const限定了常量值,讓集合不能添加內(nèi)容,但是foo確實變量,所以可以直接替換為非常量值
void main(){
var foo = const [1,2,3];
// 將變量修改為非const值
foo = [4,5,6];
// 此時就可以修改二兩
foo.add(7);
print(foo); // [4, 5, 6, 7]
}
final關(guān)鍵值不能修飾常量值,
如果使用final修飾常量值就會報錯
void main(){
var foo = final [1,2,3]; // 直接過錯
}
6. dart的數(shù)據(jù)類型
6.1 類型的了解
常用的數(shù)據(jù)類型
-
Numbers( 數(shù)值)
int
double
-
Strings (字符串)
String
-
Booleans (布爾)
bool
-
List (集合,也被稱為數(shù)組)
在Dart中,數(shù)組是列表對象, 所以大多數(shù)人只是稱他們?yōu)榱斜?/p>
-
Map(字典)
通常來說 Map 是一個鍵值對相對的對象, 鍵和值可以是任何類型的對象,每個鍵
不常用的類型
- Set
- Rune
- Symbol
不常用的方法在這里就不羅列了, 之后有用到咱們在說.
這些類型都可以被初始化為字面量,因為在 Dart 所有的變量終究是一個對象(一個類的實例), 所以變量可以使用 構(gòu)造涵數(shù) 進行初始化。一些內(nèi)建類型擁有自己的構(gòu)造函數(shù)。
實例:
void main(){
String str = "字符串";
print(str); // 字符串
}
6.2 數(shù)值類型
Dart 語言的 Number 有兩種類型:
一種是int ,一種是double
- int:其取值通常位于 -253和 253-1 之間
- double:64-bit (雙精度) 浮點數(shù),符合 IEEE 754 標準。
int 和 double 都是 num的亞類型。
void main(){
// 定義數(shù)值類型
// 整數(shù)類型不包含小數(shù)點
int num1 = 23; // init 只能是整型,如果賦值浮點型就報錯
double num2 = 22.5; // double可以是整型也可以是浮點型
num2 = 21;
print(num1);
print(num2);
}
6.3 字符串類型
字符串的創(chuàng)建
- 使用單引號
'',雙引號"" - 使用三個 引號
'''或雙引號"""創(chuàng)建多行字符串 - 使用
r創(chuàng)建原始raw字符串
6.3.1 定義單行字符串
void main(){
// 單行字符串
var str1 = '這是單行字符串';
var str2 = "這是單行字符串";
String str3 = '這是單行字符串';
String str4 = "這是單行字符串";
print(str1);
print(str2);
print(str3);
print(str4);
}
6.3.2 定義多行字符串
定義多行字符串的字面量是三個單引號或三個雙引號
語法
var str = ''' ''';
或
var str = """ """;
void main(){
// 單行字符串
var str1 = '''
這是多行字符串
這是多行字符串
''';
var str2 = """
這是多行字符串
這是多行字符串
""";
String str3 = '''
這是多行字符串
這是多行字符串
''';
String str4 = """
這是多行字符串
這是多行字符串
""";
print(str1);
print(str2);
print(str3);
print(str4);
}
6.3.3 使用r創(chuàng)建字符串
void main(){
String str = r"Hello World";
print(str); // Hello World
}
了解即可
6.3.4 字符串的拼接
void main(){
String str1 = '你好';
String str2 = "dart";
// 1\. 使用加好拼接字符串
print(str1 + ' ' + str2 ); // 你好 dart
// 2\. 使用$ 拼接字符串
print("$str1 $str2"); // 你好 dart
// 3\. 如果需要運算可以使用${}語法
int num = 20;
int num2 = 30;
print("運算結(jié)果:${num + num2}"); // 運算結(jié)果:50
}
6.3.5 字符串和數(shù)字相互轉(zhuǎn)換的方
void main(){
// 字符串轉(zhuǎn)為數(shù)字類型
var one = int.parse("123");
print(one); // 123
var point = double.parse("123.11");
print(point); // 123.11
// 數(shù)字類型轉(zhuǎn)字符串類型
var str = 123.toString();
print(str); // 123
var strpoint = 123.111.toString();
print(strpoint); // 123.111
// double轉(zhuǎn)字符串先得小數(shù)位數(shù)
var strpoint2 = 123.161.toStringAsFixed(2);
print(strpoint2); // 123.11
}
6.4 布爾類型
在dart中定義布爾類型的關(guān)鍵字是bool
布爾值只有個true,false,它們都是編譯時常量。
void main(){
// 定義布爾類型
bool flag1 = true;
bool flag2 = false;
print(flag1);
print(flag2);
}
添加判斷判斷
void main(){
// 定義布爾值
bool flag = true;
// 條件判斷
if(flag){
print("真");
}else{
print("假");
}
}
要注意dart條件判斷沒有隱式類型轉(zhuǎn)換
void main(){
var num = 123;
var num2 = '123';
if(num == num2){
print("num和num2的類型和值都相等");
}else{
print("num和num2的類型或者值不相等");
}
}
// 答應(yīng)不相等, == 不會進行類型轉(zhuǎn)換
6.5 集合類型 (List)
集合就像我們js里面的數(shù)組,只是叫法不一樣
定義集合
字面量定義集合
void main(){
// 定義集合
// 1\. 字面量的方式定義集合
var list = ["張三","李四",'王五', 123];
// 打印集合
print(list);
// 打印集合長度
print(list.length);
// 打印集合中的某一個值
print(list[1]);
}
通過List 構(gòu)造函數(shù)創(chuàng)建集合
void main(){
// 定義集合
// 2\. 通過List 構(gòu)造函數(shù)創(chuàng)建集合
List list = new List();
// 給集合添加內(nèi)容
list.add("張三");
list.add(123);
list.add(true);
print(list);
}
指定集合內(nèi)容的類型
void main(){
// 定義集合
// 3\. 指定集合內(nèi)容類型
List list = new List<String>();
// <String> 指定集合list里每一項只能為字符串類型
list.add("張三");
// 給list添加了一個不是字符串類型的值會報錯
list.add(123);
print(list);
}
6.6 Maps類型
Map 通常也被稱之為 字典或者 hash ,也是一個無序的集合,里面 包含一個 key-value 對。map 把 key 和 value 關(guān)聯(lián)起來可以 方便獲取數(shù)據(jù)。
有點類似于JS中的JSON對象, JS中的普通對象,屬性可以不用加引號, dart中Maps類型屬性一定要加引號(單引雙引都可以)
所以注意, JavaScript 對象Object 不是 Maps。
void main(){
// 定義Maps類型;
// 1\. 字面量定義map
var map = {
"name":"wuwei",
'age': 18,
"work": ["程序員", "外賣員"]
};
print(map);
// map操作
// map的操作不能使用點語法,只能使用中括號語法
// 中括號語法單引雙引都可以
print(map['name']);
print(map["age"]);
}
除了字面量定壓力Map外,還可以采用構(gòu)造函數(shù)定義Map
void main(){
// 定義Maps類型;
// 2\. 構(gòu)造函數(shù)定義Map
Map map = new Map();
map['name'] = 'wuwei';
map["work"] = ["程序員", "外賣員"];
print(map);
}
注意點:
- 鍵和值都可以是任何類型的對象。
- 每個 鍵 只出現(xiàn)一次, 而一個值則可以出現(xiàn)多次
7. 判斷數(shù)據(jù)類型
在dart中可以使用is關(guān)鍵字來判斷數(shù)據(jù)類型
void main(){
// 判斷數(shù)據(jù)類型
// 通過 is關(guān)鍵字
// var str = '123';
var str = 123;
if(str is String){
print("String 類型");
}else if(str is int){
print("int 類型");
}else{
print("其他 類型");
}
}