Flutter (二) Dart 語言基礎詳解 (異常,類,Mixin, 泛型,庫)

異常

Exception 類型

  • 延遲加載異常: DeferredLoadExceptionjson

  • 格式異常 : FormatException安全

  • 整數除零異常: IntegerDivisionByZeroExceptionmarkdown

  • 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 類型

  • 抽象類實例化錯誤 : AbstractClassInstantiationErrorasync

  • 參數錯誤 : ArgumentErroride

  • 斷言錯誤 : 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

  • 1553157226(1).jpg

  • 代碼

    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 順序問題:

    1. 若是 2 個或多個超類擁有相同簽名的 A 方法,那麼子類會以繼承的最後一個超類中的 A 方法爲準。
    2. 固然這是子類沒有重寫 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 區別

    1. Java 中的泛型信息是編譯時的,泛型信息在運行時是不存在的。
    2. 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();    
    }
    複製代碼
  • 選擇性載入

    1. show 只載入庫的某些部分
    2. 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();
    }
    複製代碼
  • 延遲載入

    1. 使用 deferred as 導入
    2. 使用標識符調用 loadLibrary() 加載庫;
    import 'MyLib1.dart' deferred as defelib;//延遲載入
    
    void main(){
      //延遲載入
      deferredLoad();
    }
    
    //延遲載入
    //可提升程序啓動速度
    //用在不常使用的功能
    //用在載入時間過長的包
    void deferredLoad() async{
      await defelib.loadLibrary();
      var test = defelib.Test;
    }
    複製代碼
  • 自定義庫

    1. 建立一個 A 庫 a .dart
    2. 建立一個 B 庫 b.dart
    3. 建立一個 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();
    }
    
    
        
    複製代碼

感謝

Dart 語法學習官網;

相關文章
相關標籤/搜索