Dart 學習備忘錄

Dart 官方文檔學習筆記,記錄 Dart 特色和區別於其它語言之處html

#基本特色web

  • 任何變量都是對象,包括基本類型,全部對象都繼承自 Object 類
  • 強類型,自帶類型推斷,但也可指定類型
  • 有泛型
  • 支持最外層函數定義,也支持類的靜態方法與對象的實例方法,函數中可定義內部函數
  • 支持最外層變量定義,也支持類的靜態成員和對象字段
  • 沒有表示私有公用的關鍵字,以「_」開頭的標識符表示庫中私有
  • 標識符以字母或「_」開頭,後面可隨意組合
  • 語句末尾要加分號

#變量與類型express

  • 不指定類型定義變量的關鍵字是var,會根據初始化的值推斷類型,但一旦肯定後不可賦給其它類型的值
  • 如須要定義可變類型的變量,可以使用關鍵字dynamic或指定類型爲Object
  • 任何類型變量沒有初始化,值都爲null,表示「沒有」的只有null
  • 表示常量的關鍵字是final和const,他們能夠代替var關鍵字或寫在類型以前
  • const是編譯時常量,在編譯時肯定,不可定義爲實例變量;final是運行時常量,在第一次使用時肯定;一個常量是const類型也暗示必然是final類型
  • const也可定義爲其它const的算式結果,在類中定義需與static一塊兒
  • const可寫在變量或構造函數前用來定義常值,常量表示引用關係不可變,常值表示值自己不可變
  • 數值類型num,有兩個子類int,double,int可進行按位運算,沒有基本類型的概念,因爲int,double都是num的子類,定義爲num的變量能夠在int、double間多態
  • 數值轉字符串用int.parse('1'),double.parse('1.1'),字符串轉數值用1.toString(),3.14159.toStringAsFixed(2)
  • 字符串字面量中可用${}引用表達式,或直接$引用標識符
  • 兩個字面相同的字符串相等
  • 可用連續三個單引號或雙引號表示多行字符串
  • 字符串前加字母 r 則不處理轉義
  • 布爾類型bool,全部須要判斷的地方只能傳入嚴格的bool結果
  • List類型,在定義時會推斷泛型
  • Map類型,key可爲任意類型,在定義時會推斷泛型,用{}字面量定義的會推斷爲Map類型
  • 在用構造函數新建對象時,可不用new關鍵字
  • 當用map[key]取值時,如沒有此key,會返回null
  • UTF-16字符用\uxxxx表示,其它長度編碼的UTF字符(不是4位)要加{}:\u{xxxxx}
  • 可經過#獲取標識符的Symbol,壓縮會改變標識符的名稱但不會改變它的Symbol

#函數json

  • 函數的返回值、參數可設定類型也可不設,無返回值的函數返回類型可設爲void
  • 只有一個表達式的函數可寫成箭頭函數
  • 函數的可選參數分爲命名參數和位置參數
  • 命名參數的定義:
void enableFlags({bool bold, bool hidden}) {...}
複製代碼
  • 命名參數的調用:
enableFlags(bold: true, hidden: false);
複製代碼
  • 命名參數可用在參數不少很複雜的狀況,定義時時,可經過@required肯定其爲必須的,需引入package:meta/meta.dart或package:flutter/material.dart包:
const Scrollbar({Key key, @required Widget child})
複製代碼
  • 在函數定義時,形參表最後可用[]獲取位置參數:
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
複製代碼
  • 可選參數可經過 = 設置默認值,不設置默認值爲null
  • 應用必須有一個main函數:
void main() {
  
}

或

void main(List<String> arguments) {
  
}
複製代碼
  • 函數定義式(包括前面帶上名字的箭頭函數)至關於定義了一個閉包類型的變量,等價於定義並將一個匿名函數賦值給一個變量,但不能夠同時定義命名函數又賦值給變量bash

  • 做用域遵循詞法做用域,做用域是靜態肯定的,函數可以使用其定義時的變量多線程

  • 任何函數都有返回值,如爲顯示指明則返回null,故函數調用式必定是表達式閉包

  • 多元運算符的版本由最左邊一個參數決定異步

  • ~/:整除(向下取整)async

  • ==規則:若是涉及到null,必須兩邊都爲null則返回true,不然返回false;若是不涉及null,返回左邊參數的x.==(y)方法結果ide

  • is;is!:判斷一個對象是(不是)一個類的實現(包括子類)

  • as:將一個對象強轉爲一個類,若是該對象爲null或不是該類將報錯

  • ??=:若是爲null就賦值,不然不動

  • ^:按位異或

  • ~:按位取反

  • ??:條件運算符,若是左邊不爲null返回左邊,不然返回右邊

  • ..:級聯運算符,表示把左邊對象中的右邊成員取出進行某項操做再返回該對象

  • ?.:條件獲取成員,若是左邊爲null也不報錯而是返回null

#結構語句

  • else if中間分開一個空格

  • 能夠用forEach()和for-in遍歷可迭代對象,好比Map,List

  • switch分支比對的目標必須是編譯時常量,被比較實例必須是同一類(不能夠是子類),不可重寫==

  • 異常分爲Exception和Error兩類以及它們的子類

  • 方法無需進行異常聲明和檢查

  • 能夠throw任意對象,固然不建議這樣作

  • throw式是一個表達式

  • on指明捕捉的異常類型,catch指明異常參數,二者可配合使用,有了on可省略catch

  • catch有第二個參數StackTrace

  • 在catch塊中,可用rethrow關鍵字繼續拋出該異常

  • 就算遇到未捕獲的異常,也會先執行完finally中的異常再拋出

#面向對象

  • 類只能夠有一個父類,子類可以使用任意級父類的內容
  • 對於定義了常量構造函數的類,可用const關鍵字調用,調用相同常量構造函數(包括參數)構造的對象是同一個實例
  • 在一個常量做用域內(好比一個常量Map)都是常量,不須要再重複寫const了
  • 對象類信息的字段是runtimeType
  • 類中聲明瞭初始值的字段,字段會在constructor以前初始化
  • 在類中只有命名衝突時才須要this.xx
  • 能夠以以下的形式定義命名構造函數
Point.origin() {
    x = 0;
    y = 0;
  }
複製代碼
  • 任何構造函數都不會被繼承
  • 若是沒有特別指明,子類的構造函數中第一步會調用父類的默認構造函數
  • 子類構造函數的執行順序是:初始化字段表->父類構造函數->子類構造函數
  • 定義了構造函數會覆蓋掉默認構造函數,如父類沒有默認構造函數,子類構造函數需在函數體大括號前用冒號手動指明調用父類構造函數
class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}
複製代碼
  • 構造函數大括號前還可用冒號指明初始化字段表,經常使用來設置final字段:
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
    : x = json['x'],
      y = json['y'] {
  print('In Point.fromJson(): ($x, $y)');
}
複製代碼
  • 沒有函數體,而是用冒號指向調用其餘構造函數,稱爲重定向構造函數:
class Point {
  num x, y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}
複製代碼
  • 固定不變的對象可設爲編譯時常量,經過類定義中的常量構造函數實現:
class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);
}
複製代碼
  • 若是不但願構造函數老是新建一個實例,添加了factory關鍵字成爲工廠構造函數,工廠構造函數不可訪問this:
class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}
複製代碼
  • 全部實例的字段都有getter,非final的有setter,也可經過get、set關鍵字設置
  • 沒有定義函數體的方法稱爲抽象方法,抽象方法只可出如今抽象類中
  • 經過abstract關鍵字可定義抽象方法,除非定義了工廠構造函數,抽象類不能被實例化
  • 任何類都是一個接口,一個類要實現一個接口(類),用關鍵字impliments,能夠實現多個接口
  • 子類經過@override註解重寫父類方法
  • 可經過operator關鍵字重寫運算符(重寫 == 運算符需同時重寫 hashCode的getter)
  • 調用一個實例的未實現方法,將會報錯,觸發1.實例類型爲dynamic;或2.實例定義了該方法(爲抽象)同時重寫了noSuchMethod()
  • 枚舉類型定義形式爲:
enum Color { red, green, blue }
複製代碼
  • 枚舉類型中的每個值都有一個index屬性,枚舉類的values屬性可得到全部的值
  • 不能夠繼承、混入、實現枚舉類型,也不能夠實例化枚舉類型
  • 建立mixin的要求是繼承Object,不聲明構造函數,不調用super
  • 使用mixin在類定義後使用關鍵詞with,和混入多個mixin
  • 可用static關鍵字定義類變量和類方法,類變量在第一次使用時纔會初始化;類方法不可以使用this;對於公有功能,建議使用函數而不是類方法
  • 除了限制類型,泛型還能起到指代類型,減小代碼的做用:
abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}
複製代碼
  • 可在集合的字面量定義中使用泛型
var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};
複製代碼
  • 集合類型機制是reified(不一樣於Java的erasure),會在運行時保留
print(names is List<String>);
複製代碼

#異步處理

  • 處理異步過程的類是Future和Stream,函數是async/await函數
  • async關鍵字寫在參數表與函數體之間
  • 可將main函數定義爲async函數
  • 不須要返回值的async函數返回類型可設爲Future<void>
  • 可用await for等待遍歷stream的全部值,但要當心使用:
await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}
複製代碼
  • 同步generator用sync*關鍵字定義,返回Iterable,異步generator用async*關鍵字定義,返回Stream
  • 遞歸generator函數中調用自身時可用yield*關鍵字提升性能

#其它

  • 當給類實現了call()方法,類的實例就能夠像函數同樣被調用了

  • 經過isolate處理多線程,isolate有單獨的內存堆,相互之間不可訪問

  • 經過typedef關鍵字,可定義函數的具體(參數、返回值)類型:

typedef Compare<T> = int Function(T a, T b);

int sort(int a, int b) => a - b;

void main() {
  assert(sort is Compare<int>); // True!
}
複製代碼
  • 文檔級註釋用///或/**開頭,編譯器會忽略文檔級註釋,但其中用[]括起來的內容仍然能夠連接
相關文章
相關標籤/搜索