簡(jiǎn)介:
??Dart是谷歌開(kāi)發(fā)的跨平臺(tái)的計(jì)算機(jī)高級(jí)語(yǔ)言。Dart是面向?qū)ο蟮摹㈩惗x的、單繼承的語(yǔ)言。它的語(yǔ)法類似C語(yǔ)言(更加類似于swift或者kotlin),可以轉(zhuǎn)譯為JavaScript,支持接口(interfaces)、混入(mixins)、抽象類(abstract classes)、泛型(reified generics)、可選類型(optional typing)和靜態(tài)推斷類型sound type system。
Hello world! :
??main()函數(shù)是Dart的入口函數(shù),也是所有Dart語(yǔ)言的開(kāi)端:
void main() {
print('Hello, World!');
}
Dart中重要的概念:
1.Dart中一切皆對(duì)象:
??在其它面向?qū)ο笳Z(yǔ)言中變量類型一般包含基礎(chǔ)數(shù)據(jù)類型和對(duì)象類型(或者引用類型),例如swift或者java。在Dart中,聲明的每個(gè)變量都是一個(gè)類的對(duì)象;無(wú)論是數(shù)字(numbers),函數(shù)(functions)和null都是對(duì)象;并且除了null(如果你啟用了sound null safety),所有對(duì)象繼承自Object類。
2.Dart中是強(qiáng)引用類型的(strong):
??不像swift或者OC中有weak弱引用,Dart中的變量或者屬性都是strong強(qiáng)引用的。雖然Dart是強(qiáng)類型的,但類型注釋是可選的,因?yàn)镈art可以推斷類型。在下面的代碼中,number被推斷為int類型:
var number = 23;
print(number.runtimeType); // 打印int
3.Dart中是空安全的(null safety):
??null safety是在Dart 2.12中引入的。當(dāng)您選擇null safety時(shí),您代碼中的類型默認(rèn)情況下是不可為空的,這意味著值不能為空,除非您說(shuō)它們可以為空。示例代碼如下:
int? number2; // number2可以為空也可以是int類型的值
number2 = null;
number2 = 34;
int number3;
number3 = null; // 報(bào)錯(cuò):number3不能為null
4.Dart中可以推斷確定變量類型:
??Dart中推斷確定變量的類型有兩種,一種是在編譯時(shí),一種是在運(yùn)行時(shí)。在Dart中,聲明變量和屬性基本都是編譯時(shí)已經(jīng)確定其類型,但是用關(guān)鍵字dynamic修飾的變量和屬性是在編譯時(shí)才能確定的。
??dynamic修飾的變量和屬性的值進(jìn)行任何成員訪問(wèn),但可能會(huì)失敗,并在運(yùn)行時(shí)拋出異常。如果您確實(shí)想要那種有風(fēng)險(xiǎn)但靈活的動(dòng)態(tài)分派,那么使用dynamic是合適的類型。
??否則,更喜歡使用Object?或Object。在訪問(wèn)值之前,依賴于is檢查和類型提升,以確保值的運(yùn)行時(shí)類型支持希望訪問(wèn)的成員。
Object? number; // 可以為任意類型的值
dynamic number2; // 可以為任意類型的值
number = null;
number = 12;
number.toString();
number = '123'; // 上一行number是int值,可以改變變量的類型
// print(number + 1); // 編譯時(shí)報(bào)錯(cuò),number2是String值
if (number is int) { // 判斷類型
print(number + 1);
}
print(number.runtimeType);
number2 = null;
number2 = 12;
number2 = '123';
if (number2 is int) { // 判斷類型
print(number2 + 1); // 編譯時(shí)報(bào)錯(cuò)
}
print(number2 + 1); // 編譯時(shí)不報(bào)錯(cuò),運(yùn)行時(shí)報(bào)錯(cuò),number2是String值
5.Dart支持泛型類型:
??Dart支持泛型類型,如List<int>(整數(shù)列表)或List<Object>(任何類型的對(duì)象列表)。
6.Dart支持頂級(jí)函數(shù)和變量
??Dart支持頂級(jí)函數(shù)(如main())和變量,以及綁定到類或?qū)ο蟮暮瘮?shù)或者變量(分別為靜態(tài)方法或者靜態(tài)變量和實(shí)例方法或者實(shí)例變量)。還可以在函數(shù)中創(chuàng)建函數(shù)(嵌套函數(shù)或局部函數(shù))。實(shí)例變量有時(shí)被稱為字段或?qū)傩浴?/p>
7.Dart沒(méi)有權(quán)限修飾符:
??與Java不同,Dart沒(méi)有public、protected和private權(quán)限修飾符。如果標(biāo)識(shí)符以下劃線(_)開(kāi)頭,則它是其庫(kù)或者類的私有。
8.私有變量、常量、函數(shù)都以下劃線開(kāi)頭:
??標(biāo)識(shí)符可以以字母或下劃線(_)開(kāi)頭,然后是這些字符和數(shù)字的任意組合。
class Some {
// 靜態(tài)變量,類屬性
static int type = 0;
// 實(shí)例變量,實(shí)例屬性,實(shí)例字段
late final String name;
// 私有屬性
late String _privateProperty;
// 可供外界訪問(wèn)方法
void show() {
_show();
}
// 靜態(tài)方法,類方法
static void showType() {
print(type);
}
// 私有函數(shù)
void _show() {
print(_privateProperty);
}
}
9.Dart中的表達(dá)式和語(yǔ)句:
??Dart語(yǔ)法中有expressions( 表達(dá)式有運(yùn)行時(shí)值)和 statements(語(yǔ)句沒(méi)有運(yùn)行時(shí)值 )。 例如,條件表達(dá)式condition ? expr1 : expr2 的值可能是 expr1 或 expr2 。 將其與 if-else 語(yǔ)句相比較,if-else 語(yǔ)句沒(méi)有值。 一條語(yǔ)句通常包含一個(gè)或多個(gè)表達(dá)式,相反表達(dá)式不能直接包含語(yǔ)句。
var number = 1;
final bool isBigger;
if (number > 10) {
isBigger = true;
}
else {
isBigger = false;
}
var isBigger2 = (number > 10) ? true : false;
10.Dart中警告和錯(cuò)誤
??Dart工具可以報(bào)告兩種問(wèn)題:warnings(警告)和errors(錯(cuò)誤)。警告只是表示您的代碼可能無(wú)法工作,但它們不會(huì)阻止您的程序執(zhí)行。錯(cuò)誤可以是編譯時(shí)的,也可以是運(yùn)行時(shí)的。編譯時(shí)錯(cuò)誤會(huì)阻止代碼執(zhí)行;運(yùn)行時(shí)錯(cuò)誤會(huì)導(dǎo)致在執(zhí)行代碼時(shí)引發(fā)異常。
Dart中的關(guān)鍵字
| 關(guān)鍵字 | 關(guān)鍵字 | 關(guān)鍵字 | 關(guān)鍵字 |
|---|---|---|---|
| abstract 2 | else | import 2 | show 1 |
| as 2 | enum | in | static 2 |
| assert | export 2 | interface 2 | super |
| async 1 | extends | is | switch |
| await 3 | extension 2 | late 2 | sync 1 |
| break | external 2 | library 2 | this |
| case | factory 2 | mixin 2 | throw |
| catch | false | new | true |
| class | final | null | try |
| const | finally | on 1 | typedef 2 |
| continue | for | operator 2 | var |
| covariant 2 | Function 2 | part 2 | void |
| default | get 2 | required 2 | while |
| deferred 2 | hide 1 | rethrow | with |
| do | if | return | yield 3 |
| dynamic 2 | implements 2 | set 2 |
??避免使用這些詞作為標(biāo)識(shí)。但是,如果有必要,標(biāo)記有上標(biāo)的關(guān)鍵字可以是標(biāo)識(shí)符。
標(biāo)識(shí)符命名規(guī)則:
- 變量的名稱必須有數(shù)字,字母,下劃線和美元符($)組成
- 標(biāo)識(shí)符不能以數(shù)字開(kāi)頭
- 標(biāo)識(shí)符不能是保留字或關(guān)鍵字,見(jiàn)關(guān)鍵字說(shuō)明
- 標(biāo)識(shí)符是區(qū)分大小寫的;例如:
name和Name不是同一個(gè)變量 - 標(biāo)識(shí)符(變量和函數(shù))一定要通俗名義
變量:
1.變量的定義:
??變量定義有三種常見(jiàn)的方法,一種是var定義,一種是指定具體類型的定義,還有一種是dynamic定義。
??在空安全模式下(null safety),變量在使用之前必須被初始化賦值,除非該變量允許為空(例如int?)。
1.1var定義變量:
??var定義變量,不明確變量的類型,Dart自己會(huì)有類型檢查,會(huì)根據(jù)var關(guān)鍵字在定義變量時(shí)所賦予的初值的類型明確變量的類型。var定義變量根據(jù)賦值的時(shí)機(jī)分為兩種情況:一種是定義時(shí)隨即賦值;一種是先聲明變量,在之后代碼中另行賦值。
1.1.1var定義變量隨即賦值:
??上述中說(shuō)到,在賦值時(shí)確定了變量類型,在賦值之后,可以賦值其它類型嗎?代碼如下:
var number2 = 12; // 等價(jià)于 int number2 = 12;
number2 = 14;
var result = number2 + 1; // 正常運(yùn)行
// number2 = null; // 編譯報(bào)錯(cuò)
// number2 = '123'; // 編譯報(bào)錯(cuò)
??如代碼所示,這種聲明變量并賦值的變量,其后無(wú)法進(jìn)行其它類型的賦值,它與指定具體類型定義變量等價(jià)。
1.1.2var定義變量后,另行賦值:
??與1.1.1中問(wèn)題進(jìn)行對(duì)比:
var number; // 等價(jià)于 Object? number;
number = 12;
number = null; // 不會(huì)報(bào)錯(cuò)
number = '123'; // 不會(huì)報(bào)錯(cuò)
// var result = number + 1; // 編譯時(shí)通過(guò),運(yùn)行時(shí)報(bào)錯(cuò),上一行代碼表示,number為String類型
var result2 = number + '1'; // 正常運(yùn)行
??如代碼所示,這種聲明并賦值的變量,其后可以進(jìn)行其它類型的賦值,并且該變量的類型與最近一次賦值的類型相同;但是之后對(duì)其進(jìn)行已賦值過(guò)的類型進(jìn)行操作,編譯時(shí)不會(huì)報(bào)錯(cuò),運(yùn)行時(shí)會(huì)報(bào)類型不匹配的錯(cuò)誤;該定義變量與指定類型為Object?變量等價(jià)。
1.2指定具體類型的定義變量:
int number = 1;
String str = '123';
1.3動(dòng)態(tài)變量即dynamic定義的變量:
??dynamic定義的變量,編譯時(shí)不會(huì)進(jìn)行其類型的確定,而是在運(yùn)行時(shí)確定;并且該變量可以進(jìn)行任意類型的操作,編譯時(shí)不報(bào)錯(cuò),只有在運(yùn)行時(shí)才會(huì)報(bào)錯(cuò);其運(yùn)行時(shí)的類型與最近一次賦值的類型相同。
dynamic number = 1;
var result = number + '1'; // 編譯通過(guò),運(yùn)行時(shí)報(bào)類型不匹配錯(cuò)誤
number = '123';
var result2 = number + '4'; // 正常運(yùn)行
??dynamic一般用于泛型(以后會(huì)講到),且必須對(duì)其類型有確切的掌握,不然運(yùn)行時(shí)報(bào)錯(cuò)就不可避免了。
2.初始值(Default value):
- 具有可空類型的未初始化變量的初始值為
null, - 在空安全模式下(
null safety),局部變量在使用之前必須被初始化賦值,除非該變量允許為空(例如int?)。 - 頂級(jí)和類變量是延遲初始化的,且使用之前必須被初始化賦值。
int? number2;
print(number2);
int number;
// print(number); // 空安全模式下,number沒(méi)有初始化,且不能為空,所以報(bào)錯(cuò)
number = 2;
print(number); // 正常運(yùn)行
class Some {
// static int type; // 報(bào)錯(cuò)
static int type = 1;
}
常量:
定義:
??不更改的變量或者初始化后無(wú)法更改的變量就是常量,在Dart中聲明常量用關(guān)鍵字const或者final。
const的final聯(lián)系:
- 都是編譯時(shí)常量;
- 只能初始化賦值一次,其后無(wú)法修改值;
- 在類中都可以和
static一起使用表示類級(jí)別的屬性。
const的final區(qū)別:
-
const常量聲明時(shí)可以省略,而final不能省略; - 類中聲明屬性和字段使用
final,不用const; -
const常量為編譯時(shí)常量,聲明時(shí)必須初始化賦值,而final常量還是運(yùn)行時(shí)常量可以先聲明再賦值(即常說(shuō)的懶加載),但是final常量必須在使用前進(jìn)行初始化賦值; -
const修飾對(duì)象時(shí),對(duì)象的屬性無(wú)法修改,而final修飾對(duì)象,對(duì)象屬性可以修改。
內(nèi)置類型:
Dart支持的類型:
-
Numbers (數(shù)值類型
int,double) -
Strings (字符串
String) -
Booleans (
bool) -
Lists (
List,常見(jiàn)的數(shù)組) -
Sets (集合
Set) -
Maps (哈希表或者字典
Map) -
Runes (
Runes;通常被“characters”API所取代) -
Symbols (符號(hào)
Symbol) - 空值
null(空類Null)
Dart特殊的類型:
-
Object:除Null外的所有Dart類的超類; -
Future和Stream:用于異步支持; -
Iterable:用于for-in循環(huán)和同步生成器函數(shù); -
Never:表示一個(gè)表達(dá)式永遠(yuǎn)不能成功完成求值,通常用于總是拋出異常的函數(shù); -
dynamic:表示要禁用靜態(tài)檢查,通常你應(yīng)該使用Object?代替; -
void:表示該值從未被使用。通常用作返回類型。
Numbers類型:
??整形數(shù)值類型(int);其取值范圍,不大于64位的整數(shù)值,取決于平臺(tái);在本地平臺(tái)上,值可以從-263到263 - 1。在web上,整數(shù)值表示為JavaScript數(shù)字(64位浮點(diǎn)值,沒(méi)有小數(shù)部分),取值范圍從-253到253 - 1。
??double類型:64位(雙精度)浮點(diǎn)數(shù),由IEEE 754標(biāo)準(zhǔn)指定。
??int和double都是 num的子類。num類型包括基本操作符,如+、-、/和*,在這里您還可以找到abs()、ceil()和floor()等方法。(位操作符,如>>,定義在int類中。)如果num及其子類型沒(méi)有您要尋找的內(nèi)容,那么dart:math庫(kù)可能有。
var x = 1;
var hex = 0xDEADBEEF;
var exponent = 8e5;
var y = 1.1;
var exponents = 1.42e5;
num n = 1; // x可以是int或者double
n += 2.5;
assert((3 << 1) == 6); // 0011 << 1 == 0110
assert((3 | 4) == 7); // 0011 | 0100 == 0111
assert((3 & 4) == 0); // 0011 & 0100 == 0000
Strings類型:
- String類型包含一個(gè)UTF-16代碼單元序列;
- 可以用
''或者""初始化賦值; - 可以用
r初始化賦值; - 可以用
‘’‘’‘’或者""""""初始化多行字符串; - 可以用
+拼接字符串; - 可以用
==判斷字符串內(nèi)容相同。
String s1 = '123';
String s2 = "123";
String s3 = r"123";
String s4 = '''123
456
789
''';
String s5 = """123
456
789
""";
var s6 = "I am " + "Lucy!";
print("object" == "object"); // true
Booleans類型:
-
bool類型,兩個(gè)值true和false;它們都是編譯時(shí)常量; - 條件判斷沒(méi)有隱式類型轉(zhuǎn)換。
var number = 123;
var str = '123';
if (number == str) {
print("隱式轉(zhuǎn)換");
}
else {
print("沒(méi)有轉(zhuǎn)換"); // 沒(méi)有轉(zhuǎn)換
}
Lists類型:
-
List中元素可以重復(fù); - 支持
if,for,...,...?等語(yǔ)法;
??List數(shù)組類型,常見(jiàn)初始化和操作代碼如下:
var intList = [1, 2, 3];
List<int> intList3 = <int>[];
var list2 = [0, ...intList];
var strList = ['Car', 'Boat','Plane',];
List<String> strList2 = <String>[];
var hasZheng = true;
var strList3 = [
'周',
'吳',
if (hasZheng) '鄭',
];
var listOfInts = [1, 2, 3];
var listOfStrings = [
'#0',
for (var i in listOfInts) '#$i'
];
print(listOfStrings);
Sets類型:
-
Set中元素唯一; - 支持
if,for,...,...?等語(yǔ)法;
??Set集合類型,常見(jiàn)初始化和操作代碼如下:
var intSets = {1, 1, 1};
var intSets2 = <int>{};
intSets2.add(2);
intSets2.addAll(intSets);
print(intSets); // {1}
print(intSets2); // {2, 1}
var hasZheng = true;
Set<String> strSets = {'周', '吳', if (hasZheng) '鄭'};
Set<String> strSets2 = {...strSets, '王'};
print(strSets2); // {周, 吳, 鄭, 王}
Maps類型:
-
Map是一個(gè)關(guān)聯(lián)鍵(key)和值(value)的對(duì)象的集合; - 鍵和值都可以是任何類型的對(duì)象;
- 每個(gè)鍵只出現(xiàn)一次,但您可以多次使用相同的值;
- 支持
if,for,...,...?等語(yǔ)法;
??Set集合類型,常見(jiàn)初始化和操作代碼如下:
var nameMap = {"first" : "周", "second" : "吳"};
nameMap['third'] = "鄭";
Map<int, String> someMap = {1 : "周", 2 : "吳"};
var someMap2 = {1 : "周", 2 : "吳", ...someMap};
print(nameMap); // {first: 周, second: 吳, third: 鄭}
print(someMap2); // {1: 周, 2: 吳}