Dart語法詳解(三)——進階篇


想學Flutter,就請關注這個專欄
Flutter系列(一)——詳細介紹java

Flutter系列(二)——與React Native進行對比
git

Flutter系列(三)——環境搭建(Windows)
github

Flutter系列(四)——HelloWorld
bash

Dart語言詳解(一)——詳細介紹網絡

Dart語言詳解(二)——基本語法異步

文檔歸檔:
github.com/yang0range/…async

前言

在上一篇文章,咱們詳細的介紹了Dart語法的一些基本語法,這一這篇文章,咱們繼續介紹Dart的語法的相關知識。ide

異常

不論是Java語言仍是Dart語言,都有異常,以及異常的捕獲,可是不一樣的是dart中的異常都是非檢查異常,方法能夠不聲明可能拋出的異常,也不要求捕獲任何異常。函數

Dart提供了Exception和Error類型以及一些子類型來定義異常。不過,還能夠自定義異常,只要拋出非空對象做爲異常便可,不要求必須是Exception和Error對象,可是通常來講都是拋出Exception和Error類型。post

接下來咱們詳細介紹一下。

Exception類型


Error類型


異常拋出

異常的拋出和Java仍是很相像的。

//拋出Exception對象
  throw new FormatException('格式異常');

  //拋出Error對象
  throw new NullThrownError();

  //拋出任意非null對象
//  throw '這是一個異常';

複製代碼

異常捕獲

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);
  }
}
複製代碼

類的概念和Java當中相似。
可是也有很大的區別。

  • 類的構造
//java中寫法
class P {
  double x;
  double y;

  P(int x, int y) {
    this.x = x;
    this.y = y;
  }
}


//dart建議寫法
class P {
  num x;
  num y;
  Point(this.x, this.y);

複製代碼
  • 重定向構造函數
class P { 
  num x; 
  num y; 

  Point(this.x, this.y); 

  //重定向構造函數,使用冒號調用其餘構造函數
  P.alongXAxis(num x) : this(x, 0);
}

複製代碼
  • 類的Get和Set方法
class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}

複製代碼
  • mixins

Mixins是Dart裏面的一個全新概念,簡單來講,用來複用多個類之間的代碼,減小耦合,換句話來講,能夠從中擴展方法(或變量)而不擴展類。

不用不知道,一用起來才發現,真香!

下面具體舉例說明一下:

例如,咱們有這麼一個職業關係圖:

image.png
image.png

從圖中能夠梳理出如下關係:

  • 工程師類目,有軟件工程師和建築工程師等,他們共同點都是工程師。
  • 教師類目有美術教師,IT教師等,他們共同點都是教師。

若是咱們用Java來實現的花

//工做者
abstract class Worker {
    public abstract void doWork();//工做者須要工做
}

//工程師
class Engineer extends Worker {
    @Override
    public void doWork() {
        System.out.println("工程師在工做");
    }
}

//教師
class Teacher extends Worker {
    @Override
    public void doWork() {
        System.out.println("教師在教學");
    }
}

//軟件工程師
class SoftwareEngineer extends Engineer {

}

//建築工程師
class BuildingEngineer extends Engineer {

}

//美術教師
class ArtTeacher extends Teacher {

}

//IT教師
class ITTeacher extends Teacher {

}
複製代碼

若是用Dart來實現

//工做者
abstract class Worker {
  void doWork();//工做者須要工做
}

//工程師
class Engineer extends Worker {
  void doWork() {
    print('工程師在工做');
  }
}

//教師
class Teacher extends Worker {
  void doWork() {
    print('教師在教學');
  }
}

//軟件工程師
class SoftwareEngineer extends Engineer {

}

//建築工程師
class BuildingEngineer extends Engineer {

}

//美術教師
class ArtTeacher extends Teacher {

}

//IT教師
class ITTeacher extends Teacher {

}
複製代碼

從以上來看,彷佛Java和Dart沒有什麼特別大的區別,由於Dart也是單繼承。

下面,咱們再把場景豐富一下。

image.png
image.png

經過圖形或表格能夠看出,軟件工程師和IT教師都具有修電腦的能力,建築工程師和美術教師都具有手繪的能力,可是這些能力都是他們特有的,不是工程師或者教師具有的能力,因此不能在他們的父類中實現。

若是使用Java,那麼咱們天然就想到了使用interface。

interface CanFixComputer {
    void fixComputer();
}

interface CanDesignSoftware {
    void designSoftware();
}

//軟件工程師
class SoftwareEngineer extends Engineer implements CanFixComputer, CanDesignSoftware {

    @Override
    public void fixComputer() {
        System.out.println("修電腦");
    }

    @Override
    public void designSoftware() {
        System.out.println("設計軟件");
    }
}

//IT教師
class ITTeacher extends Teacher implements CanFixComputer {

    @Override
    public void fixComputer() {
        System.out.println("修電腦");
    }
}
複製代碼

可是,咱們知道Dart當中沒有interface的概念,但並不意味着這門語言沒有接口,事實上,Dart任何一個類都是接口,你能夠實現任何一個類,只須要重寫那個類裏面的全部具體方法。

若是要用Dart來實現的化,只須要將interface修改爲abstract class。

可是咱們發現,fixComputer這個接口被繼承了兩次,而且兩次的實現都是同樣的,這裏就出現了代碼重複和冗餘的問題。怎麼辦呢?在java中咱們有接口的default實現來解決這個問題(這是一個java8出現的不得已的方案。)

可是,有了mixins以後,這件事就變得不那麼難了。

abstract class CanFixComputer {
  void fixComputer() {
    print('修電腦');
  }
}

abstract class CanDesignSoftware {
  void designSoftware() {
    print('設計軟件');
  }
}

//軟件工程師
class SoftwareEngineer extends Engineer
    with CanFixComputer, CanDesignSoftware {

}

//IT教師
class ITTeacher extends Teacher with CanFixComputer {

}

main() {
  ITTeacher itTeacher = new ITTeacher();
  itTeacher.doWork();
  itTeacher.fixComputer();
  SoftwareEngineer softwareEngineer = new SoftwareEngineer();
  softwareEngineer.doWork();
  softwareEngineer.fixComputer();
  softwareEngineer.designSoftware();
}
複製代碼

經過以上代碼,咱們能夠看到這裏不用implements,更不是extends,而是with。

每一個具備某項特性的類再也不須要具體去實現一樣的功能,接口是無法實現功能的,而經過繼承的方式雖然能實現功能,但已經有父類,同時不是一個父類,又不能多繼承,因此這個時候,Dart的Mixin機制就比Java的接口會高效,開發上層的只須要關心當前須要什麼特性,而開發功能模塊的關心具體要實現什麼功能。

關於順序的理解

既然是with,那應該也會有順序的區別。

class First {
  void doPrint() {
    print('First');
  }
}

class Second {
  void doPrint() {
    print('Second');
  }
}

class Father {
  void doPrint() {
    print('Father');
  }
}

class Son1 extends Father with First,Second {
  void doPrint() {
    print('Son1');
  }
}

class Son2 extends Father with First implements Second {
  void doPrint() {
    print('Son2');
  }
}

main() {
  Son1 son1 = new Son1();
  son1.doPrint();
  Son2 son2 = new Son2();
  son2.doPrint();
}
複製代碼

輸出的內容是:

Son1
Son2
複製代碼

經過這裏,咱們能夠看到
能夠看到,不管是extends、implements仍是mixin,優先級最高的是在具體類中的方法。

下一個例子:

class First {
  void doPrint() {
    print('First');
  }
}

class Second {
  void doPrint() {
    print('Second');
  }
}

class Father {
  void doPrint() {
    print('Father');
  }
}

class Son1 extends Father with First,Second {

}

class Son2 extends Father with First implements Second {

}

main() {
  Son1 son1 = new Son1();
  son1.doPrint();
  Son2 son2 = new Son2();
  son2.doPrint();
}
複製代碼

輸出的結果:

Second
First
複製代碼

其實在Son2中implements只是說要實現他的doPrint()方法,這個時候其實具體實現是First中Mixin了具體實現。
而Mixin的具體順序也是能夠從代碼倒過來看的,最後mixin的優先級是最高的。

泛型

在Dart當中,有不少的容器對象,在建立對象時均可以定義泛型類型,這一點和Java是同樣的。
例如:

var list = List<String>();
  list.add('aaa');
  list.add('bbb');
  list.add('ccc');
  print(list);

  var map = Map<int, String>();
  map[1] = 'aaaa';
  map[2] = 'bbbb';
  map[3] = 'cccc';
  print(map);
複製代碼

和Java的區別

Java中的泛型信息是編譯時的,泛型信息在運行時是不存在的。

Dart的泛型類型是固化的,在運行時也有能夠判斷的具體類型。

異步

Future

說到異步就不得不說到Future。

Future與JavaScript中的Promise很是類似,表示一個異步操做的最終完成(或失敗)及其結果值的表示。簡單來講,它就是用於處理異步操做的,異步處理成功了就執行成功的操做,異步處理失敗了就捕獲錯誤或者中止後續操做。一個Future只會對應一個結果,要麼成功,要麼失敗。

由於Flutter返回的都是一個Fluter對象,天然就能夠採用鏈式方法。

  1. Future.then 任務執行完後的子任務
  2. Future.delayed 延遲執行
  3. Future.catchError 若是異步任務發生錯誤,咱們能夠在catchError中捕獲錯誤。
  4. Future.whenComplete 完成的時候調用。
  5. Future.wait 等待多個異步任務都執行結束後才進行一些操做。

Async/await

若是業務邏輯中有大量異步依賴的狀況,將會出現上面這種在回調裏面套回調的狀況,過多的嵌套會致使的代碼可讀性降低以及出錯率提升,而且很是難維護,這個問題被形象的稱爲回調地獄(Callback Hell)。

這個問題在JS當中十分的突出,Dart幾乎是一樣的問題,而後把相關方法平移過來。因此功能和用法也幾乎是相同的。

  • async用來表示函數是異步的,定義的函數會返回一個Future對象,可使用then方法添加回調函數。
  • await 後面是一個Future,表示等待該異步任務完成,異步完成後纔會往下走;await必須出如今 async 函數內部。

只有async方法才能使用await關鍵字調用方法
若是調用別的async方法必須使用await關鍵字。

Stream

Stream 也是用於接收異步事件數據,和Future 不一樣的是,它能夠接收多個異步操做的結果(成功或失敗)。 也就是說,在執行異步任務時,能夠經過屢次觸發成功或失敗事件來傳遞結果數據或錯誤異常。 Stream 經常使用於會屢次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。

Stream.fromFutures([
  // 1秒後返回結果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 拋出一個異常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒後返回結果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});
複製代碼

輸出

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3
複製代碼

Isolates-隔離

全部Dart代碼都在隔離區內運行,而不是線程。每一個隔離區都有本身的內存堆,確保不會從任何其餘隔離區訪問隔離區的狀態。

最後

經過這三篇文章,咱們基本上把Dart語言的所涉及,所涵蓋的內容都講述了一遍。

這些仍是偏理論多一些,語法仍是在多實踐,多寫,多練的過程中來找到其中的真諦。

接下來,咱們就開始詳細的展開Flutter的介紹了!
Flutter已是Top20的軟件庫,經過接下來的一系列的文章,但願我和你們一塊兒來學習Flutter,一塊兒進步,一塊兒有所收穫,掌握將來技術主流的主動權!

有什麼好的建議,意見,想法歡迎給我留言!

歡迎關注公共號

關注公衆號會有更多收穫!

image.png
image.png

動動小手指點贊,收藏,轉發一鍵三連走一波吧!

參考文檔

kevinwu.cn/p/ae2ce64/
www.jianshu.com/p/06604077d…《Flutter實戰》

相關文章
相關標籤/搜索