Dart | 淺析dart中庫的匯入與拆分

Vadaski發表於2018-08-01

前言

最近十分熱門的跨平臺框架使用了一門比較生僻的程式語言dart。dart語言本身深受早期一些程式語言的影響。特別是Smalltalk,Java和JavaScript。我是從Java語言向dart過度的,一開始感覺很不錯,快速就對這門語言有了一個初步的認識,並能夠寫小段程式碼了。

但在flutter的不斷學習過程中,我遇到了不少因為dart的一些語法而產生的困惑。回過頭來看dart的語法之後產生了一些頓悟,在此記錄下來希望能幫助到更多的學習者。

你將學到什麼

  • 外部庫的完全匯入與不完全匯入
  • 匯入新的庫對變數名稱空間的影響
  • 庫的拆分——part

匯入

完全匯入

我們假定需要在A庫裡使用B庫的某些方法,我們需要將B庫import進A庫。這是我們十分熟悉的。

import 'B.dart';
複製程式碼

不僅如此,dart的匯入語句還適用於任意url。我們可以使用網路上的某個資源(dart檔案)作為外部庫匯入。

import 'http://hello/hello.dart';
複製程式碼

但是我們不推薦這樣做。因為網路資源隨時可能會發生變化。一旦改變,我們的程式將會被破壞。

真正嚴謹的做法是:

import'package:hello/hello.dart';
複製程式碼

使用 package:匯入方式會執行一個常駐的封裝了程式碼位置資訊的包管理器。

一個庫可以使用的全部物件包括這個庫本身宣告的,以及通過匯入語句從其他庫匯入的。在dart:core中定義的物件是隱式匯入的。而一個庫對外可使用的物件稱為庫匯出的名稱空間。

理論上一個庫的名稱空間中不應有名稱相同的兩個物件,否則你需要使用別名。

import 'test2.dart'
class Test{
    static final hello = new Test();
}
複製程式碼
class Test2{
    static final hello = new Test2();
    Test2 _test = new Test2();
}
複製程式碼

在這段程式碼中,Test2被import進了Test庫,我們在test庫中是無法看到Test2的私有變數_test的,所以這個變數將不會被匯入到名稱空間。

在Dart中,當前庫所宣告的物件優先順序高於任何物件,因此匯入的庫中有頂層物件並不會有想象中那樣具有破壞性。但是如果你訪問了一個匯入的物件,另外一個匯入後續又新增了一個同名物件,那麼新匯入的物件會覆蓋原有物件。

不完全匯入

Dart提供了額外的機制來控制匯入到庫內的物件:命名組合器show和hide。

show

當我們只需要一個龐大庫中某一個或某幾個(少數)的物件的時候,我們可以選擇使用show組合器進行匯入。這樣可以使你的庫更加健壯。

import 'package:math' show Random;
複製程式碼

在這行程式碼中,我們只匯入了math庫中的Random物件。

show組合器接收一個名稱空間和一個識別符號列表,並將識別符號列表中出現的物件保留在名稱空間。

hide

當我們在一個庫種希望不匯入某一個或某幾個物件的時候,我們可以使用hide組合器進行匯入。

import 'package:math' hide Random;
複製程式碼

這段程式碼將匯入math庫但不匯入math庫種的Random物件。實現方式與show類似。同樣也是接收一個名稱空間和識別符號列表,並將識別符號列表中出現的物件從名稱空間中丟棄,然後產生一個新的名稱空間。

解決變數名衝突的辦法

解決此問題最好的辦法是將引入的庫加上別名。

import 'package:math' as mymath;
複製程式碼

通過這種方式我們可以完美避開不同庫之間因為匯入而使得變數名衝突的問題。

庫的拆分

有的時候一個庫可能太大,不能方便的儲存在一個檔案當中。Dart允許我們把一個庫拆分成一個或者多個較小的part元件。或者我們想讓某一些庫共享它們的私有物件的時候,我們需要使用part。

Dart | 淺析dart中庫的匯入與拆分

Dart | 淺析dart中庫的匯入與拆分
這裡我們可以看到,parttest2.dart是part of 'parttest.dart'的檔案,可以理解為,parttest2是parttest的一部分。在part test2.dart中,我們並沒有引入package:flutter/material.dart包就直接繼承了StatelessWidget,是因為,在part中,import進來的庫是共享名稱空間的。

不是所有的庫都有名稱,但如果使用part來構建庫,那麼庫必須要命名。

library xxx;
複製程式碼

每個子part都存放在各自的檔案中。但是它們共享同一作用域,庫的內部名稱空間,以及所有的匯入(import)。

在上述例子中,我們可以看到,part data.dart中Data類中呼叫了part data.g.dart的DataFromJson(json)方法,而第二個part中構建DataFromJson(json)方法返回Data物件並沒有在part data.g.dart定義。它們彼此之間是共用的名稱空間。並且私有物件也是可以互相訪問的。

part也可以通過url指明它所在的庫,但是我們同樣也是不推薦這樣做的。

Part與import有什麼區別

可見性: 如果說在A庫中import了B庫,A庫對B庫是不可見的,也就是說B庫是無法知道A庫的存在的。而part的作用是將一個庫拆分成較小的元件。兩個或多個part共同構成了一個庫,它們彼此之間是知道互相的存在的。

作用域:import不會完全共享作用域,而part之間是完全共享的。如果說在A庫中import了B庫,B庫import了C庫,A庫是沒有辦法直接使用C庫的物件的。而B,C若是A的part,那麼三者共享所有物件。並且包含所有匯入。

寫在最後

以上就是Dart中庫的匯入與拆分的全部內容,若有描述不準確或錯誤之處歡迎各位大牛指正!

之後我會更新一系列flutter乾貨,如果你喜歡的話可以關注我或者給我一個好評哦!我會更新更有動力的。

相關文章