簡述:git
這是一篇譯文,來自於Dartlang官方在Medium上的一篇文章,文章中說到Dart正在從新設計它的類型系統,而且即將要加入可空類型和非空類型(這一點和Kotlin語言是極其的類似,正由於這種可空和非空的類型系統的嚴格劃分,才能讓Kotlin很好地避免NPE的問題)。爲何要翻譯一篇這樣的文章,算爲咱們下一篇語法篇Dart類型系統和泛型作一個鋪墊。由於當你進入Dart類型系統,你會發現它其實是一個不嚴格的類型系統,好比泛型型變安全方面。github
翻譯說明:算法
原標題: Dart nullability syntax decision: a?[b] or a?.[b]數組
原文地址: medium.com/dartlang/da…安全
原文做者: Kathy Walrathmarkdown
Dart正在從新設計其類型系統,以便於各個類型都存在可空(該類型的表達式能夠有null值)或者非空兩種類型。今年晚些時候,咱們將告訴您具體的發佈時間和流程。可是Dart默認狀況下都將不可爲null, 而且當你須要爲null的時候,必須使用特殊的語法來講明當前類型容許使用null值。ide
例如,當你要聲明一個整型能夠爲null,則須要在聲明的類型後面加一個?
函數
int? someInt; // someInt變量能夠爲null
複製代碼
若是你看過Kotlin、Swift或C#代碼,可能對問號?
語法並不陌生。可是也存在一些不一樣的地方---特別是常常用來訪問集合和數組中的下標([]
)運算符。C#和Swift都是使用?[]
,而目前Dart(以及ECMAScript)的計劃是使用?.[]
語法。源碼分析
e1?.[e2] //若是e1爲null,就返回null; 不然就返回e1[e2]的值
複製代碼
這篇文章主要說明作這個定案背後的緣由,並鼓勵你能有一些本身的想法和建議。這些內容大部分都是基於Bob Nystrom對issue #376的評論,該評論總結了Bob和NNBD規範負責人LeafPetersen之間的討論。post
e1?[e2]
與e1?.[e2]
兩種方式都有各自的優勢。
e1?[e2]
:
!
運算符(即便它是可空類型,也可使用它在表達式後面添加,表示它的值不爲null)的語法: e1![e2]
e1.[e2]
:
e1..[e2] //級聯語法
e1?..[e2] // 可空檢查的級聯語法
複製代碼
e1?.e2()
{ e1 ? [e2] : e3 }
咱們花了一段時間嘗試找到避免?[]
歧義的方法。問題在於你沒法判斷這這段代碼{e1 ? [e2] : e3}
是不是一個包含條件表達式結果的set集合,或者是一個包含可空檢查下標key的map集合。
若是咱們經過添加括號方式來消除歧義,能夠選擇在整個表達式周圍添加--{ (e1 ? [e2] : e3) }
--能夠明確地把它當作一個set集合。或者咱們能夠將括號包裹第一部分的周圍--{ (e1?[e2]) : e3) }
--能夠明確把它當作一個map集合。可是在沒有括號的狀況下,解析器就不知道該怎麼作了。
對於這種歧義有多種解決方案,可是彷佛沒有一個使人滿意的解決方案。一種方法是依靠空格來區分選項。在這種方法中,由於這個空格在?
和[
之間,因此你老是會把e1 ? [e2]
做爲條件表達式的前半部分。並且你老是將e1?[e2]
做爲可空檢查的下標,由於這兩個標記之間沒有空格。可是依賴空格確實對開發者體驗很差。
從理論上來講,在格式化代碼中,依靠空格不是問題。可是不少用戶將未格式化的Dart代碼編寫做爲格式化程序的輸入。所以,在該語言的每一個地方,這樣輸入格式將變得對空格更加敏感且脆弱。到目前爲止,在Dart中這類狀況不多見,這是一個不錯的語法特性。(好比- - a
和--a
都是有效的但卻有着不一樣的含義
忽略歧義問題,使用圓點語法還有另外一個緣由: 若是咱們爲其餘運算符(例如e1?.+(e2)
等)添加可檢測空值的形式,則可能須要使用點號。
咱們爲NNBD討論的另外一項功能是可檢查null的調用語法。若是咱們在此處不須要點,則它也存在相同的歧義問題:
var wat = { e1?(e2):e3 }; // Map or set?
複製代碼
不管咱們爲?[
這種形式給出什麼解決方案,它都必須一樣適用於?(
這種形式。 最後,考慮鏈式調用下標的示例:
someJson?[recipes]?[2]?[ingredients]?[pepper]
複製代碼
在咱們看來,這看起來不太好。它看上去不像是方法鏈,而更像是中綴運算符的某種組合-有點像??
運算符。將其與如下代碼進行比較:
someJson?.[recipes]?.[2]?.[ingredients]?.[pepper]
複製代碼
在這裏,它顯然是一個方法調用鏈。視覺上看起來也很明顯,由於用戶須要快速瞭解有多少表達式會出現空短路。
總結這麼多,彷佛看起來咱們應該使用?.[
下面列舉一些緣由:
?.
做爲單個"空檢查"令牌)咱們一直對反饋和建議很重視,對於這種語法給出反饋最好方式就是對語言issue #376發表評論(或者給一些評論點贊)。那麼在使用的時候,請能夠考慮查看咱們正在使用其餘不錯的語言特性。
您能夠在這裏找到更多信息:
NNBD:
Dart語言的其餘變動和特性:
其實這篇文章主要就是討論一下,關於在Dart語言中對於數組或集合下標可空語法的表達是應該用a?[b]
仍是使用a?.[b]
. 而後做者給出一些爲何會使用a?.[b]
的緣由。經過這篇文章,咱們應該還獲得一個信息就是Dart正在重構它的整個類型系統,它會像Kotlin那樣把類型系統分爲可空類型和非空類型,從而實現使得整個類型系統更加完備和嚴謹。
Dart可空和非空類型已經處於實驗階段,可是在Dart2.x源碼中已經在開始使用了。
好比dart中的ListQueue
的源碼
//
class ListQueue<E> extends ListIterable<E> implements Queue<E> {
static const int _INITIAL_CAPACITY = 8;
List<E?> _table;//聲明List<E?>集合,泛型類型參數E爲可空類型
int _head;
int _tail;
int _modificationCount = 0;
/// Create an empty queue.
///
/// If [initialCapacity] is given, prepare the queue for at least that many
/// elements.
ListQueue([int? initialCapacity])//聲明可空類型的int
: _head = 0,
_tail = 0,
_table = List<E?>(_calculateCapacity(initialCapacity));
static int _calculateCapacity(int? initialCapacity) {
//對可空類型initialCapacity作空檢查
if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) {
return _INITIAL_CAPACITY;
} else if (!_isPowerOf2(initialCapacity)) {
return _nextPowerOf2(initialCapacity);
}
assert(_isPowerOf2(initialCapacity));
return initialCapacity;
}
...
}
複製代碼
可是須要注意的是目前尚未直接開放給開發者,還處於experiment階段。
因此,相信很快Dart中的可空和非空類型將會轉正正式使用,到那時候學過Kotlin、Swift或C#的開發者將會對Dart類型系統有更深的認識。有了這一篇的鋪墊,咱們下一篇就能夠正式進入Dart中的類型系統了,下一篇咱們會將Dart中可選類型、泛型、協變、泛型類型具體化等。
這裏有最新的Dart、Flutter、Kotlin相關文章以及優秀國外文章翻譯,歡迎關注~~~