簡介
null可能是大家在編寫程式中最為頭疼的一個東西,稍不留意的情況下就有可能使用到了這個空字元。所以dart在2.12引入了nll safety,預設情況下強制所有的型別都不為null,只有在你認為它可以為null的時候才可以設定為null。
雖然有了null safety,但是這裡還有一些我們需要考慮的null的最佳實踐。
不需要初始化物件為null
在dart2.12之後,所有的物件都強制為非空的,除非你顯示指定其為可空的物件。
如果一個物件可以為空,那麼我們可以這樣指定:
String? name;
如果定義一個物件可以為空,那麼對dart來說會隱式對其初始化為null。
所以下面的顯示初始化為null是完全沒有必要的:
String? name=null;
同樣的,如果引數是一個可以為空的物件,那麼dart也會將其初始化為null,我們也沒有必要顯示去設定其值:
void echoName(String? name){
print(name);
}
null的三元操作符
所謂三元就是有三個變數,我們常見的三元操作符就是?:,通常來說是這樣用的:
name==null?true:false;
上面的邏輯實際上是把一個null轉換成了一個bool型別。
為了實現這個功能,dart提供了一個更加簡潔的操作符??, 可以這樣使用:
name??false;
上面的程式碼表示如果name是空,則返回false。
注意,這裡只是返回值改變了,但是name值本身並沒有變化,也不會將name從一個可為空的型別,變成不為空的型別。所以如果我們在if語句裡面對字元進行判斷,則還是需要顯示進行null的比較:
int measureMessage(String? message) {
if (message != null && message.isNotEmpty) {
// dart知道message不為空
return message.length;
}
return 0;
}
如果這樣編寫,則會出現異常:
int measureMessage(String? message) {
if (message?.isNotEmpty ?? false) {
//dart並不知道message不為空
return message!.length;
}
return 0;
}
如果在使用中需要判斷型別是否為空,則不要使用late
late是做什麼用的呢?late表示該型別目前不會初始化,但是會在未來的某個時間對其進行初始化。
所以,如果你用late表示某個型別,那麼在後續使用的時候是不需要進行手動判斷該型別是否為空的。
如果你仍然要手動判斷,那麼就沒必要設定該型別為late。
本地變數的型別提升
dart有一個非常好的特性,就是當我們判斷一個變數不為空之後,該變數就會被提升為非空變數。
當提升為非空變數之後,就可以自由訪問該非空變數內部的屬性和方法了。
但是可惜的是,dart中的型別提升只是針對與local變數或者引數而言的,對於類變數或者是top level的變數並不適用,所以我們需要將這些變數拷貝到本地變數,從而使用型別提升的特性。
我們看下面的例子:
class UploadException {
final Response? response;
UploadException([this.response]);
@override
String toString() {
var response = this.response;
if (response != null) {
return 'Could not complete upload to ${response.url} '
'(error code ${response.errorCode}): ${response.reason}.';
}
return 'Could not upload (no response).';
}
}
其中UploadException中的response是一個頂級變數,雖然我們對其進行測試是否為空,但是在使用的過程中還是不能直接訪問其內部的屬性,因為response可能為空。
為了使用dart的型別提升的特性,我們可以將頂級的變數賦值給一個本地變數,從而在null測試之後,自動將其提升為非空的型別,從而直接訪問其內部的屬性。
總結
以上就是dart中null用法的最佳實踐。
本文已收錄於 http://www.flydean.com/29-dart-null-effective/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!