引言
最近flutter發展的如火如荼,而Dart作為flutter的開發語言,瞭解一下伐?
語言特徵
dart 中一切皆物件 dart這個特徵和java很像,所有變數、方法都是物件,那怕僅僅是個數字或字串
入口函式
在dart專案中,必須宣告一個入口函式main,這也很java,程式從main函式開始執行(習慣使用js的需要注意這一點)。
void main(){
print('hello dart!')
}
複製程式碼
變數宣告
- 一般宣告變數必須明確型別,型別明確後不能改變,未賦值預設值都是null
int i = 2; i = '3' ; // error:i為int型別,不能賦值字串型別 複製程式碼
- var 可以宣告任意型別的變數,賦值後型別不能再改變
var i; i = 2; i = 3; i = '4'; // error: var 變數賦值後,型別不能再改變 複製程式碼
- dynamic 可以宣告動態型別的變數,每次賦值型別不受限制
dynamic d = 1; d = '123'; // 變數型別確定後還可以再賦值其他型別 複製程式碼
- final 變數只能賦值一次,宣告時必須初始化
final a = 1; a = 2; // error: final變數只能賦值一次,再次賦值報錯 final b = [2]; b[0] = 1; b.add(2); // final 雖然不能再次賦值,但是可以改變他成員變數的值 複製程式碼
- const 變數是編譯時常量,是一種特殊的final變數
const a = 1; a = 2; // error: const變數只能在初始化時賦值 const b = [2]; b.add(2); // error: const 變數中的成員變數也不可再次改變 複製程式碼
方法
- 一般定義方法須明確入參個數、型別及出參的型別
// 方法定義,明確入參和出參,編譯時可以做型別校驗,提前發現一些錯誤 int add(int m, int n) { return m + n; } void main() { int a = add(50, 30); String b = add('50', 30); // error: 入參型別和出參型別不正確,編譯不通過 } 複製程式碼
- 如果不明確定義方法入參和出參引數型別,編譯時無法進行型別檢查
// 出參和入參的型別可以忽略,如果忽略,編譯時無法進行型別檢查 add( m, n) { return m + n; } void main() { int a = add(50, 30); String b = add('50', 30); // 可以通過編譯,但在執行時會報異常 } 複製程式碼
- 方法入參也可以使用基於命名或位置的可選引數
// 可選位置引數 // 可選引數後面不能再有引數 int add(int m, [int n]) { int sum = m; if (n != null) { sum += n; } return sum; } void main() { print(add(1)); print(add(1, 2)); } 複製程式碼
// 可選命名引數 int add({int m, int n}) { int sum = 0; if (m != null) { sum += m; } if (n != null) { sum += n; } return sum; } void main() { print(add()); print(add(m: 1)); print(add(n: 2)); print(add(m: 1, n: 2)); } 複製程式碼
- 定義方法入參時可以定義可選引數的預設值,預設值必須是編譯時常量
// 預設引數值 // 預設值只能給可選引數設定 // 位置可選引數匹配順序是從左到右的,即便有預設引數值 int add(int m, [int n = 0, int i]) { var sum = m + n; if (i != null) { sum += i; } return sum; } void main() { print(add(1)); print(add(1, 2)); } 複製程式碼
- 箭頭函式只能跟一個表示式,不能使用語句和程式碼塊(前端開發人員要特別注意,和js的箭頭函式不同)
// => 函式 void main() { var add = (int m, int n) => m + n; var sub = (int m, int n) => return m - m; // error: ruturn 是程式碼語句,箭頭函式不能使用程式碼語句 add(1 , 2); } 複製程式碼
- 當方法作為引數傳遞給高階方法時,可以使用匿名方法
也可以使用箭頭函式為高階方法傳參// 匿名函式 void main() { var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums']; list.forEach((i) { print(list.indexOf(i).toString() + ': ' + i); }); } 複製程式碼
// 匿名函式 void main() { var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums']; // 轉換為箭頭函式時,要去掉語句後面的分號, // 有分號就是語句,沒有分號就變成了表示式,符合箭頭函式要求 list.forEach((i) => {print(list.indexOf(i).toString() + ': ' + i)}); // 或 list.forEach((i) => print(list.indexOf(i).toString() + ': ' + i)); } 複製程式碼
- Dart是靜態作用域語言,編譯時變數的作用域就已經確定(這點也和js不同,前端開發人員需注意)
// 靜態作用域 int a = 5; class Test { int a = 6; int getA() { return a; } } void main() { var obj = new Test(); print(obj.getA()); // 6 var fun = obj.getA; print(fun()); // 6 } 複製程式碼
操作符
- 除法( / ), 整除(~/)
void main() { print('5/2 = ${5 / 2}'); // 5/2 = 2.5 print('5~/2 = ${5 ~/ 2}'); // 5~/2 = 2 } 複製程式碼
- 型別轉換(as), 型別判斷(is、is!), as 只能從父型別轉子型別, is 判斷變數是某種型別, is!和is相反,判斷變數不是某種型別
void main() { num a = 123; // print(a.isOdd); // error: isOdd 不是num的成員變數 print((a as int).isOdd);// isOdd 是int的成員方法,所有a必須轉換成int型別後再呼叫 print('a is not String ? ${a is! String}'); // a is not String ? true print('a is int ? ${a is int}'); // a is int ? true } 複製程式碼
- ??= 為值為null的變數賦值
void main() { var a; a ??= 1; // 賦值前a = null,賦值後 a=1 a ??= 2; // 賦值前 a = 1, 賦值後 a=1 print(a); // 1 } 複製程式碼
- expr1 ?? expr2, 等價於 expr1 != null ? expr1 : expr2
void main() { var a; var b = 1; print(a ?? b); // 1 a = 0; print(a ?? b); // 0 } 複製程式碼
- 級聯操作(
..
)可以在同一個物件上連續呼叫多個函式及訪問成員變數// '..'不同於'.',不要求函式有返回值,'..'相當於普通函式執行後返回‘this’ class Car { void move(String direction, double distance) { print('小汽車向${direction}行駛了${distance} 千米'); } Car run(String direction, double distance) { print('小汽車向${direction}行駛了${distance} 千米'); return this; } } void main() { Car car = new Car(); car..move('東', 3)..move('南', 4)..move('西', 4)..move('北', 4); car..move('東', 3)..run('西', 3)..run('北', 4).run('西', 4).run('北', 4); } 複製程式碼
- a?.b 如果a為null,則返回null,否則返回a.b
void main() { int a; // print(a.isOdd); // error: a未賦值,不能訪問成員變數和成員函式 print(a?.isOdd); // 相當於 if (a == null) { print(null); } else { print(a.isOdd); } } 複製程式碼
類
- 每個物件都是一個類的例項,所有的類都整合於Object
void main() { int a = 1; print(a is Object); // true } 複製程式碼
- 每個類都只能有一個父類,但是可以同時實現多個介面,一個父類可以同時被多個子類繼承
class Tiger extends Animal implements Fly, Swim { // todo } class Dog extends Animal { // todo } 複製程式碼
- 每個例項變數都會自動生成一個getter方法,Non-final例項變數還會自動生成一個setter方法
class Test { int a; // 相當於 // int _a; // int get a => _a; // set a(int val) => this._a = val; } 複製程式碼
- 定義一個和類名字一樣的方法就定義了一個建構函式,還可以帶有其他可選的識別符號,如果沒有定義,會生成一個不帶引數的預設建構函式,建構函式不會被繼承
class Parent { String name; Parent(this.name); } class Child extends Parent { Child(String name) : super(name); Child.create(String name) : super(name); } void main(){ var zhangsan = Child('張三'); var lisi = Child.create('李四'); } 複製程式碼
- 可以使用abstract來定義抽象類,抽象類不能被例項化。抽象類通常含有抽象方法,抽象方法只有方法簽名,沒有實現。
abstract class Animal { // 抽象方法 void moving(); } 複製程式碼
- 用extends來實現繼承,用implements來實現介面,使用@override來重新父類方法
class Animal { final String name; Animal(this.name); void moving() { print('${this.name}正在移動'); } } abstract class Fly { // 抽象方法 void fly(); } class Tiger extends Animal implements Fly { Tiger() : super('老虎'); @override void fly() { print('如虎添翼'); } } 複製程式碼
- 用static定義靜態變數和靜態方法
class Calculator { static int Add(int m, int n) { return m + n; } } void main(){ print(Calculator(1, 2)); } 複製程式碼
庫的使用
- 通過
import
來引入庫 - 引用內部庫
import 'dart:schema'
,如:import 'dart:io';
- 引用外部庫
import 'package:schema'
, 如:import 'package:utils/utils.dart';
- 可以通過
as
來指定庫字首,如import 'package:utils/utils.dart' as utils;
- 可以通過
show
和hide
來部分匯入庫 - 可以通過
deferred as
延遲載入一個庫
dart 核心庫
dart:core
提供了基礎型別、集合和其他少量但是非常核心的功能,dart應用會自動匯入這個庫。dart:convert
提供了一些用來轉換 JSON 和 UTF-8 的轉換器,還可以自定義 新的轉換器。dart:async
非同步程式設計通常使用回撥函式,但是 Dart 提供了另外的 選擇: Future 和 Stream 物件。dart:html
為基於web的應用提供了操作Dom元素和使用HTML5 API的功能。dart:math
提供了常用的數學運算功能。dart:io
提供了一下檔案讀寫、程式訪問、sockets等相關的功能,只有命令列應用可以使用。
PUB
pub類似於node的npm,用於管理dart應用的包,詳情參見pub.dev/
總結
瞭解了上面這些基礎語法,基本上就可以看懂一些dart示例和原始碼了,想有所成,瞭解這些還是遠遠不夠的,但是這些可以作為一個開始,作為學習dart的起點。
參考
- 官方文件:dart.dev/guides
- Pub網站: pub.dev/
- 中文官網:dart.goodev.org/
- 三十分鐘入門:www.bilibili.com/video/av327…
- 系列視訊:www.bilibili.com/video/av524…
關於我們
快狗叫車前端團隊專注前端技術分享,定期推送高質量文章,歡迎關注點贊。
文章同步釋出在公眾號喲,想要第一時間得到最新的資訊,just scan it !