Dart語言學(xué)習(xí)筆記

安裝

如果是windows系統(tǒng),點擊安裝SDK:http://www.gekorm.com/dart-windows/
如果是Mac系統(tǒng),點擊安裝SDK:https://dart.dev/get-dart
可將dart安裝后的bin目錄加入到path路徑中,打開命令行工具,使用命令dart --version確保dart已安裝到您電腦中即可。

為什么要學(xué)些這門語言

目前Google推出的最新跨端解決方案Flutter,需要采用Dart語言編寫前端代碼。Flutter是目前市面上最好的跨端應(yīng)用解決方案,另外,Dart語言學(xué)習(xí)門檻低性能好,支持動靜態(tài)編譯,并支持很多高級語言特性。

語法要點

dart語言借鑒了java,js,swift等高級的語言特性,并融入很多使用的語法糖,我們來簡要做個概括。

  • 在Dart中所有變量引用的都是對象,繼承Object,包括數(shù)字,函數(shù),null等都是對象;
  • 在Dart運行之前會解析您的代碼,通過使用類型和編譯型常量來幫助Dart捕獲異常,讓代碼運行的更高效;
  • Dart支持在方法中定義方法,函數(shù)是Dart非常重要的概念;
  • Dart沒有public,private,protected關(guān)鍵字,如果要申明私有成員變量或函數(shù)請使用_打頭;
  • 可以在代碼中加入assert斷言語句以便讓有些錯誤在編譯器就能被捕獲;

啟動入口

Dart語言也是把main函數(shù)作為入口程序。可以給main函數(shù)傳入List<String>入?yún)斫邮彰钚袇?shù)列表。

內(nèi)置類型

dart語言使用var聲明變量,和swiftid類似,在編譯階段會自動確認其類型。
dart語言只有以下幾種內(nèi)置類型:StringNumberboolMap,List,FunctionSymbolsrunes等,其中Number分為intdouble,注意沒有float之類的浮點數(shù)類型,可以對Number類型四則運算,其中取整運算符是~/,有一些常用的屬性,如isNaN,isEven(是否偶數(shù)),isOdd(是否奇數(shù))等,可以做一些簡單的類型轉(zhuǎn)換,如int.parse("1");double.parse("1.1"等,注意在Dart中沒有數(shù)組類型,而統(tǒng)一使用List;

  • 字符串:使用"""多行字符串聲明,可以使用$xx${xx}在字符串中使用變量占位符,相鄰的字符串拼接的+可省略,但拼接的內(nèi)容不能是1個空格。
  • 靜態(tài)變量:可以使用關(guān)鍵字static修飾類訪問的變量。
  • Dart字符串是UTF-16 code units字符序列,所以支持emoji表情符,如笑臉: \u{1f600};

類的使用

Dart和Java等高級語言一樣,可以定義類,并使用extends繼承類,使用@override注解聲明你要重寫的函數(shù),使用super調(diào)用重寫這個父類的函數(shù)。

image

如果要在代碼嘗試使用類中不存在的方法或?qū)嵗兞繖z測時做出反應(yīng),可以重寫noSuchMethod

可以使用abstract修飾符定義無法實例化的類;

一個類可以使用implements實現(xiàn)多個接口;

可以使用enum定義枚舉;

一個類可以通過..使用級聯(lián)調(diào)用語法,比如querySelector("#id")..text="xxx"..onClick.listen(xxx);

泛型

泛型有以下好處:

  • 減少代碼重復(fù):泛型允許您在多種類型之間共享單個接口和實現(xiàn),同時仍然利用靜態(tài)分析;
  • 代碼更友好,編譯期提醒:比如列表中的元素指定泛型類型可確保不符合類型的元素被添加;
  • 與Java不同,Dart會在運行期攜帶類型信息,如List<String>類型的列表,可以使用lists.runtimeType(),獲取到類型信息List<String>
  • 可以配合extends來限定參數(shù)類型;
  • 泛型可以被使用在包括函數(shù),函數(shù)表達式,類方法,類型參數(shù),返回類型等中;

重寫操作符

我們可以通過關(guān)鍵字operator關(guān)鍵字重寫包括:+,-,*,/,<,>,<=,>=,%,/,[],[]=,,=,<<,>>等十幾種運算符:

image

類型自動推斷

在聲明一個變量時,無需指定類型,系統(tǒng)會自動推斷,比如var m= {"a":1};var i=1;,系統(tǒng)自動認為mMap類型i整型。如果一個變量被賦值后,在后續(xù)會被另外類型的變量值覆寫,應(yīng)該使用dynamic聲明這個變量。

final和const

用來定義常量,都必須初始化,const是編譯時常量,只能用編譯時常量來初始化,但final可以用變量來初始化,比如final time = new DateTime.now();是允許的。

函數(shù)

函數(shù)類型是Function,函數(shù)可以賦值,也可以作為參數(shù)傳遞給其他函數(shù),這是函數(shù)式編程典型特征。在Dart中不能重載函數(shù),函數(shù)可以不指定返回類型(實際會返回Object),而實際上函數(shù)體可以返回任意類型,如果在函數(shù)體中沒有return,則返回null。

在我們編寫Flutter程序時,經(jīng)常會碰到函數(shù)體只是返回一個布局,那么函數(shù)體在一條語句的情況下,可以簡寫成:void printxx(num n) => print(n);,注意箭頭的用法。

另外函數(shù)的參數(shù)非常有意思,可指定可選參數(shù)(使用{}將可選參數(shù)括起來),可以通過:或=指定參數(shù)默認值,也可以使用位置參數(shù)(用[]括起來),注意位置參數(shù)如果有多個,必須跟實際傳入的是實參一一對應(yīng)。

函數(shù)可以用來賦值,比如:var uu = (msg) => "'${msg.toUpperCase()}'";,以上uu是一個函數(shù),將傳入的字符串轉(zhuǎn)換成大寫,可以直接調(diào)用uu("hello")即返回HELLO

函數(shù)也可以作為參數(shù),比如Future.delayed(new Duration(seconds: 2),(){return "hi";}),第二個參數(shù)就是一個函數(shù),函數(shù)作為參數(shù)的用法在Flutter編程中隨處可見,是一個非常重要的用法。

構(gòu)造函數(shù)

Dart是不支持函數(shù)重載的,那多個構(gòu)造函數(shù)怎么辦?我們可以使用命名構(gòu)造函數(shù),比如Text.a(this.a);Test.ab(this.a,this.b)等命令構(gòu)造函數(shù)

閉包

一個閉包是一個方法對象,不管該對象在何處被調(diào)用, 該對象都可以訪問其作用域內(nèi)的變量。方法可以封閉定義到其作用域內(nèi)的變量。比如以下代碼:

Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}
main() {
  var add2 = makeAdder(2);
  var add4 = makeAdder(4);
  assert(add2(3) == 5);
  assert(add4(3) == 7);
}

異步支持

Dart類庫有非常多的返回Future或者Stream對象的函數(shù)。 這些函數(shù)被稱為異步函數(shù)。async和await關(guān)鍵詞支持了異步編程,允許您寫出和同步代碼很像的異步代碼。

image

以上寫法在Flutter編程中經(jīng)常被用到,將異步的調(diào)用方式以同步的寫法呈現(xiàn),使得我們理解起來更加直觀。

元數(shù)據(jù)注解

元數(shù)據(jù)注解以字符開頭@,后跟對編譯時常量(如deprecated)的引用或?qū)ΤA繕?gòu)造函數(shù)的調(diào)用。元數(shù)據(jù)可以出現(xiàn)在typedef類型參數(shù)構(gòu)造函數(shù)工廠函數(shù)字段參數(shù)或變量聲明之前以及導(dǎo)入或?qū)С鲋噶钪啊D梢允褂梅瓷湓谶\行時檢索元數(shù)據(jù),所有Dart代碼都有兩個注解:@deprecated@override。你可以定義自己的元數(shù)據(jù)注解,如下:

image

之后就可以使用注解:@todo('name','ddd')

Mixin

有時候?qū)⒛承┬袨槎x為Mixin,以便讓其他類通過with來實現(xiàn)多重繼承,減少代碼冗余。比如var CC=T with A,B,表示CC類中的方法是T,A,B三個類的方法的并集,當(dāng)有函數(shù)名重名的時候,B的方法覆蓋A,T的,A方法覆蓋T的。這樣就變相支持了多重繼承。

反射

dart:mirrors 庫提供了基本的反射支持。可以通過#打頭定義Symbols,這樣在代碼混交的情況下也可以保持標識符名稱。比如你知道類名,可以直接用new Symbol("CLASSNAME")來構(gòu)建symbol。比如我們動態(tài)調(diào)用C類的d方法,d方法有一個參數(shù):

class C{
var tt = "test";
C(){};
static d(msg){print(msg);}
a(){print("C.a";)}
}
//調(diào)用類的靜態(tài)函數(shù)
ClassMirror cc = reflectClass(C);
cc.invoke(Symbol("d"), ["hello"]);
//如果調(diào)用實例函數(shù)
InstanceMirror mm = cc.newInstance(Symbol.empty, []);
mm.invoke(Symbol("a"), []);
//獲取類的成員變量
print(mm.reflectee.tt);

此外,還可以通過反射獲取注解,元數(shù)據(jù)等,具體可參考:http://www.lxweimin.com/p/d68278d19f79
Flutter中禁止使用反射。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容