異常
Exception 型別
-
延遲載入異常: DeferredLoadException
-
格式異常 : FormatException
-
整數除零異常: IntegerDivisionByZeroException
-
IO 異常 : IOException
-
隔離產生異常: IsolateSpawnException
-
超時異常 : TimeoutException
/// 部分異常參考 跟 Java 型別的異常都大同小異 main() { /// ---------------------------------異常的丟擲throw-------------------------------- //丟擲Exception物件 // throw new FormatException('格式異常'); //丟擲Error物件 // throw new NullThrownError(); //丟擲任意非null物件 // throw '這是一個異常'; /// ---------------------------------異常的捕獲try catch-------------------------------- try { throw new NullThrownError(); // throw new OutOfMemoryError(); } on OutOfMemoryError { //on 指定異常型別 print('沒有記憶體了'); // rethrow; //把捕獲的異常給 重新丟擲 } on Error { //捕獲Error型別 print('Unknown error catched'); } on Exception catch (e) { //捕獲Exception型別 print('Unknown exception catched'); } catch (e, s) { //catch() 可以帶有一個或者兩個引數, 第一個引數為丟擲的異常物件, 第二個為StackTrace物件堆疊資訊 print(e); print(s); } } 複製程式碼
Error 型別
-
抽象類例項化錯誤 : AbstractClassInstantiationError
-
引數錯誤 : ArgumentError
-
斷言錯誤 : AssertionError
-
非同步錯誤 : AsyncError
-
Cast 錯誤 : CastError
-
併發修改錯誤 : ConcurrentModificationError
-
週期初始錯誤 : CyclicInitializationError
-
Fall Through 錯誤 : FallThroughError
-
json 不支援錯誤 : JsonUnsupportedObjectError
-
沒有這個方法錯誤 : NoSuchMethodError
-
Null 錯誤 : NullThrownError
-
記憶體溢位錯誤 : OutOfMemoryError
-
遠端錯誤 : RemoteError
-
堆疊溢位錯誤 : StackOverflowError
-
狀態錯誤 : StateError
-
未實現的錯誤 : UnimplementedError
-
不支援錯誤 : UnsupportedError
類
建構函式
-
普通建構函式(Java / Dart 比較 )
void main(){ //普通建構函式 var p = new Point(1, 1); //new 可省略 var point = Point(1, 2); print(p); // print(p.runtimeType); //可以使用Object類的runtimeType屬性,獲取物件的型別 } class Point { num x; num y; //普通建構函式 Java 形式 // Point(num x, num y){ // this.x = x; // this.y = y; // } //簡化構造 Dart 形式 // Point(this.x, this.y); @override String toString() { // TODO: implement toString return 'Point(x = $x, y = $y)'; } } 複製程式碼
-
命名建構函式
void main(){ /// 命名建構函式 var p = Point.fromJson({'x':2,'y':3}); print(p); } /// 建立一個 Point 類 class Point { num x; num y; //命名建構函式 Point.fromJson(Map json){ x = json['x']; y = json['y']; } @override String toString() { return 'Point{x: $x, y: $y}'; } } 複製程式碼
-
重定向建構函式
void main(){ Point p = Point.alongXAxis(2); print(p); } class Point { num x; num y; //簡化構造 Point(this.x, this.y); //重定向建構函式,使用冒號呼叫其它建構函式 Point.alongXAxis(num x) : this(x, 0); @override String toString() { return 'Point{x: $x, y: $y}'; } } 複製程式碼
-
初始化列表
void main(){ var p = Point(3,3); print(p); /// 列印結果:Point{x: 3, y: 3,distanceFromOrigin:3.0} } /// 建立一個 Point 類 class Point { num x; num y; var distanceFromOrigin; //初始化列表 這裡的 sqrt 開方需要導包 import 'dart:math'; Point(this.x,this.y) : distanceFromOrigin = sqrt(x*y); @override String toString() { return 'Point{x: $x, y: $y,distanceFromOrigin:${distanceFromOrigin}'; } } 複製程式碼
-
呼叫超類建構函式
void main(){ var child = Child.fromJson(5, 5); var child2 = Child(5,6); print('child: ${child} ,child2: ${child2}'); //列印結果,由此可見跟 Java 一樣 父類方法先執行。 ///超類命名建構函式 ///子類命名建構函式 ///超類命名建構函式 } ///建立一個父類 class Parent{ num x; num y; Parent.fromJson(x,y):x = x,y = y{ print('超類命名建構函式'); } } ///建立一個子類 class Child extends Parent{ num x; num y; /* //如果超類沒有預設建構函式, 則你需要手動的呼叫超類的其他建構函式 Child.fromJson(x, y) : super.fromJson(x, y){ //呼叫超類建構函式的引數無法訪問 this print('子類建構函式'); }*/ Child(this.x,this.y) : super.fromJson(x, y); //在建構函式的初始化列表中使用 super(),需要把它放到最後 Child.fromJson(x,y) : x = x,y = y,super.fromJson(x,y){ print('子類命名建構函式'); } } 複製程式碼
-
常量建構函式
/// 注意:同一個物件如果定義為常量物件的話,那麼存在記憶體中的地址是相同的 void main(){ var p2 = const Point2(6, 8); print(p2); var p21 = Point2(4, 4); //建立的是非 常量物件 var p22 = const Point2(4, 4); print(identical(p22, p21)); print(identical(p2, p22)); } ///建立一個常量的建構函式 class Point2 { //定義 const 建構函式要確保所有例項變數都是final final num x; final num y; static final Point2 origin = const Point2(0, 0); //const 關鍵字放在建構函式名稱之前,不能有函式體 const Point2(this.x, this.y); @override String toString() { return 'Point2{x: $x, y: $y}'; } } 複製程式碼
-
工廠建構函式
void main(){ /// 工廠方法建構函式 var singletonl = Singleton('Java'); var singletonl2 = Singleton('Flutter'); print(identical(singletonl, singletonl2)); } ///建立一個工廠模式的類 ///第一種方試 class Singleton{ String name; //工廠建構函式無法訪問 this.所以這裡要靜態的 static Singleton _cache; factory Singleton([String name = 'singleton']){ if(_cache == null){ _cache = Singleton._newObject(name); } return _cache; } Singleton._newObject(this.name); } /// 第二種方式 class Singleton{ String name; static Singleton _cache; factory Singleton([String name = 'singleton']) => _cache ?== Singleton._newObject(name); Singleton._newObject(this.name); } 複製程式碼
-
工廠模式兩種方式
-
建立頂級函式
void main(){ var footMassage = new Massage('foot'); footMassage.doMassage(); var bodyMassage = new Massage('body'); bodyMassage.doMassage(); var specialMassage = new Massage('%#@##@##'); specialMassage.doMassage(); //列印: //腳底按摩 //全身按摩 //特殊按摩 } /工廠模式 abstract class Massage { factory Massage(String type) { switch (type) { case 'foot': return new FootMassage(); case 'body': return new BodyMassage(); default: return new SpecialMassage(); } } void doMassage(); } class FootMassage implements Massage { @override doMassage() { print('腳底按摩'); } } class BodyMassage implements Massage { @override void doMassage() { print('全身按摩'); } } class SpecialMassage implements Massage { @override void doMassage() { print('特殊按摩'); } } 複製程式碼
-
建立工廠建構函式
void main(){ ///建立頂級函式 var footMassage = massageFactory('foot'); footMassage.doMassage(); } //工廠函式 class Massage { void doMassage() { print('按摩'); } } /** * 建立頂級工廠模式 */ Massage massageFactory(String type) { switch (type) { case 'foot': return FootMassage(); case 'body': return BodyMassage(); default: return SpecialMassage(); } } class FootMassage extends Massage { @override doMassage() { print('腳底按摩'); } } class BodyMassage extends Massage { @override void doMassage() { print('全身按摩'); } } class SpecialMassage extends Massage { @override void doMassage() { print('特殊按摩'); } } 複製程式碼
-
-
set,get
void main(){ ///set get var rect = new Rectangle(1, 1, 10, 10); print(rect.left); rect.right = 12; print(rect.left); rect.buttom = 11; print(rect.top); ///列印效果 /// 1,2,1 } /** * setter getter * 每個例項變數都隱含的具有一個 getter, 如果變數不是 final 的則還有一個 setter * 可以通過實行 getter 和 setter 來建立新的屬性, 使用 get 和 set 關鍵字定義 getter 和 * setter */ class Rectangle { num left; num top; num width; num height; //宣告構造方法 Rectangle(this.left, this.top, this.width, this.height); // getter 和 setter 的好處是,可以開始使用例項變數, // 後面可以把例項變數用函式包裹起來, // 而呼叫你程式碼的地方不需要修改。 //獲取 right num get right => left + width; //set right set right(num value) => left = value - width; //獲取 button num get button => top + height; //set button set buttom(num value) => top = value - height; } 複製程式碼
-
可呼叫類
void main(){ var cf = new ClassFunction(); var out = cf("Java"," Android"," Flutter"); print('$out'); // Hi there, gang! print(cf.runtimeType); // ClassFunction print(out.runtimeType); // String print(cf is Function); // true } /**建立一個可呼叫的類*/ class ClassFunction { call(String a, String b, String c) => '$a $b $c'; } 複製程式碼
-
過載
void main(){ final v1 = Vector(2, 3); final v2 = Vector(2, 2); final r1 = v1 + v2; final r2 = v1 - v2; print([r1.x, r1.y]); print([r2.x, r2.y]); } //過載操作類 class Vector{ final int x; final int y; const Vector(this.x,this.y); //過載+ Vector operator + (Vector v){ return Vector(x+v.x, y+v.y); } //過載- Vector operator -(Vector v) { return new Vector(x - v.x, y - v.y); } } 複製程式碼
Mixin
-
圖
-
程式碼
void main() { Bicycle().transport(); Motorcycle().transport(); Car().transport(); //四輪木製腳踏車 WoodenCar().transport(); /// 列印內容 自行車: 動力元件: 兩個輪子 , 安全指數: low , 動力來源:全靠腿登 摩托車: 動力元件: 兩個輪子 , 安全指數: low , 動力來源:汽油 汽車: 動力元件: 四個輪子 , 安全指數: middle , 動力來源:汽油 四輪木製腳踏車: 動力元件: 四個輪子 , 安全指數: middle , 動力來源:汽油 } //交通工具類,擁有運輸功能 abstract class Transportation { //運輸功能 void transport(); } //雙輪交通工具 class TwoWheelTransportation { String powerUnit() => "兩個輪子"; } //四輪交通工具,一般來說安全效能為中 class FourWheelTransportation { String powerUnit() => "四個輪子"; } //安全指數中等的交通工具 class MiddleSafetyIndex { String safetyIndex() => "middle"; } //安全指數低的交通工具 class LowSafetyIndex { String safetyIndex() => "low"; } //人力發動機 class BodyEnergyTransportation { String energy() => "全靠腿登"; } //汽油能源交通工具 class GasolineEnergyTransportation { String energy() => "汽油"; } //自行車 class Bicycle extends Transportation with TwoWheelTransportation, LowSafetyIndex, BodyEnergyTransportation { @override void transport() { print( "自行車:\n動力元件: ${powerUnit()} , 安全指數: ${safetyIndex()} , 動力來源:${energy()}"); } } //摩托車 class Motorcycle extends Transportation with TwoWheelTransportation, LowSafetyIndex, GasolineEnergyTransportation { @override void transport() { print( "摩托車:\n動力元件: ${powerUnit()} , 安全指數: ${safetyIndex()} , 動力來源:${energy()}"); } } //汽車 class Car extends Transportation with FourWheelTransportation, MiddleSafetyIndex, GasolineEnergyTransportation { @override void transport() { print( "汽車:\n動力元件: ${powerUnit()} , 安全指數: ${safetyIndex()} , 動力來源:${energy()}"); } } //四輪木製腳踏車 class WoodenCar extends Car { @override void transport() { print( "四輪木製腳踏車:\n動力元件: ${powerUnit()} , 安全指數: ${safetyIndex()} , 動力來源:${energy()}"); } } 複製程式碼
-
總結
注意 extends ,with 順序問題:
- 如果 2 個或多個超類擁有相同簽名的 A 方法,那麼子類會以繼承的最後一個超類中的 A 方法為準。
- 當然這是子類沒有重寫 A 方法的前提下,如果子類自己重寫了 A 方法則以本身的 A 方法為準。
程式碼演示:
void main(){ var ab = AB(); var ba = BA(); var c = C(); var cc = CC(); print(ab.getMessage()); print(ba.getMessage()); print(c.getMessage()); print(cc.getMessage()); ///列印 B,A,C,B } class A { String getMessage() => 'A'; } class B { String getMessage() => 'B'; } class P { String getMessage() => 'P'; } class AB extends P with A, B {} class BA extends P with B, A {} class C extends P with B, A { String getMessage() => 'C'; //優先順序最高的是在具體類中的方法。 } class CC extends P with B implements A { } //這裡的 implement 只是表明要實現 A 的方法,這個時候具體實現是再 B 中 mixin 了具體實現 複製程式碼
泛型
-
容器型別的泛型,使用方式跟 Java 一樣。
void main(){ ///使用泛型,很多的容器物件,在建立物件時都可以定義泛型型別,跟Java 一樣 var list = List<String>(); list.add('1'); list.add('2'); list.add('4'); print(list); /// Map 泛型 跟 Java 也都是一樣 var map = Map<int, String>(); map[0] = '23'; map[55] = '33'; print(map); } 複製程式碼
-
泛型函式
void main(){ //泛型函式 K addCache<K, V>(K key, V value) { K temp = key; print('key:$key ,value: $value'); return temp; } var key = addCache(5, '5'); print(key); print(key.runtimeType); } 複製程式碼
-
建構函式泛型
void main(){ //建構函式泛型 var p = Phone<String>('Flutter'); print(p.text); } class Phone<T> { final T text; Phone(this.text); } 複製程式碼
-
泛型限制
void main(){ //泛型限制, 通過 extends 關鍵字限定可泛型使用的型別 var footMassage = FootMassage(); var m = Massage<FootMassage>(footMassage); m.massage.doMassage(); } //泛型限制 class Massage<T extends FootMassage > { final T massage; Massage(this.massage); } class FootMassage { void doMassage() { print('腳底按摩'); } } 複製程式碼
-
執行時判斷泛型
void main(){ //執行時可判斷泛型 var names = List<String>(); print(names is List<String>); print(names.runtimeType); } 複製程式碼
-
Dart 泛型 與 Java 區別
- Java 中的泛型資訊是編譯時的,泛型資訊在執行時是不存在的。
- Dart 的泛型型別是固化的,在執行時也有可以判斷的具體型別。
庫
-
使用核心庫
import 'dart:math'; //載入核心庫 void main(){ print(sqrt(4)); } 複製程式碼
-
載入網路請求第三方庫(pub.dartlang.org/packages?q=…)
1. 編寫 pubspec.yaml dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.0 dio: ^2.1.0 2. 程式碼編寫 import 'package:dio/dio.dart'; void main(){ gethttp(); } void getHttp() async{ try{ var response = await Dio().get("http://www.baidu.com"); print(response); }catch(e){ print(e); } } 複製程式碼
-
載入檔案
1. 新建立一個 MyLib1.dart 檔案 class DevFlutter { static DevFlutter _deFlutter; factory DevFlutter () => _deFlutter ??= DevFlutter._newInstance(); DevFlutter._newInstance(); } class Test { void start() { print(" Flutter... "); } } 2. 回到 A dart 檔案 匯入 MyLib1.dart 包 import 'Mylib1.dart' void main(){ //載入檔案 var myLib1 = MyLib(); } 複製程式碼
-
指定庫字首
///注意:如果兩個庫有衝突的識別符號,可以為其中一個或兩個庫都指定字首: import 'MyLib1.dart' as lib1; import 'MyLib2.dart' as lib2; void main(){ var myLib = lib1.MyLib(); var myLib2 = lib2.MyLib(); } 複製程式碼
-
選擇性載入
- show 只載入庫的某些部分
- hide 篩選掉庫的某些部分
import 'Mylib1.dart' as lib1 show Test; import 'Mylib2.dart' as lib2 hide Test; void main(){ var test = lib1.Test(); var lib = lib2.MyLib(); } 複製程式碼
-
延遲載入
- 使用 deferred as 匯入
- 使用識別符號呼叫 loadLibrary() 載入庫;
import 'MyLib1.dart' deferred as defelib;//延遲載入 void main(){ //延遲載入 deferredLoad(); } //延遲載入 //可提高程式啟動速度 //用在不常使用的功能 //用在載入時間過長的包 void deferredLoad() async{ await defelib.loadLibrary(); var test = defelib.Test; } 複製程式碼
-
自定義庫
- 建立一個 A 庫 a .dart
- 建立一個 B 庫 b.dart
- 建立一個 lib 庫 libs.dart
注意:程式碼中的 part,library 的含義
part: 有的時候一個庫可能太大,不能方便的儲存在一個檔案當中。Dart 允許我們把一個庫拆分成一個或者多個較小的 part 元件。或者我們想讓某一些庫共享它們的私有物件的時候,我們需要使用 part 。
library: 當沒有指定
library
指令的時候,根據每個庫 的路徑和檔名會為每個庫生成一個唯一的標籤。 所以,我們 建議你不要在程式碼中使用library
指令, 除非你想 生成庫的 API 文件。1. a.dart。 part of libs; void printA() => print('A'); 2. b.dart。 part of libs; void printB() => print('B'); 3. libs 庫 library libs; part 'util.dart'; part 'tool.dart'; void printLibs() => print('libs'); ///開始呼叫 //import 'lib/libs.dart';//載入自定義庫 void main(){ //載入自定義庫 printA(); printB(); printLibs(); } 複製程式碼