Dart 類型注解

2018-09-28 18:39 更新

類型注解

對于公有 API,最好提供類型注解。

類型注解是非常重要的文檔,它說明了相應的庫應當如何使用。為參數(shù)以及公有方法的返回類型注解有利于使用者了解 API 需要什么參數(shù)以及它能提供什么功能。

但是,如果有個 API 可以接收任何參數(shù),或者是 Dart 中無法表示的值,那么該 APi 可以不用添加注解。

對于庫內部的代碼(即便是私有的,或者是嵌套的函數(shù)),請再你認為有幫助的地方添加注解,但是不要認為你必須提供這些注解。

install(id, destPath) {    // bad
  // ...
}

在上面的代碼中,我們就不清楚 id 到底是什么。字符串?那么 destPath 又是什么呢?字符串還是文件對象?這個函數(shù)是同步的還是異步的?

Future<bool> install(PackageId id, String destPath) {     // good
  // ...
}

當你加上類型之后,這個函數(shù)的相關信息也就說明白了。

對于局部變量,最好是使用 var 而不是類型注解來聲明。

現(xiàn)在,我們更加傾向于讓函數(shù)體的代碼盡可能的簡潔,并且局部變量的類型在初始化表達式中是可以推測出來的,在這種情況下顯示聲明其類型是沒有必要的。好點的編輯器可以推測出局部變量的類型,所以自動補全功能仍然是可用的,并且你所期望的其他功能也可以正常使用。

Map<int, List<Person>> groupByZip(Iterable<Person> people) {    // good 
  var peopleByZip = new Map<int, List<Person>>();
  for (var person in people) {
    peopleByZip.putIfAbsent(person.zip, () => <Person>[]);
    peopleByZip[person.zip].add(person);
  }
  return peopleByZip;
}
Map<int, List<Person>> groupByZip(Iterable<Person> people) {    // bad
  Map<int, List<Person>> peopleByZip = new Map<int, List<Person>>();
  for (Person person in people) {
    peopleByZip.putIfAbsent(person.zip, () => <Person>[]);
    peopleByZip[person.zip].add(person);
  }
  return peopleByZip;
}

如果對代碼的運行性能有要求,那么在傳遞參數(shù)的時候,類型注解最好是用 double 或者 int 來代替 num。

單一調用點(有著穩(wěn)定輸入類型)在優(yōu)化時要比多態(tài)調用點(其輸入類型可能會發(fā)生變化)更加容易。

對于數(shù)字類型,在添加類型注解時你應該指明具體的數(shù)字類型。明確地聲明 double 或者 int 有助于使用你方法的人為之傳遞相應的參數(shù)。

在正式初始化的時候不要做類型注解。

如果一個構造函數(shù)的參數(shù)使用了 this. 來初始化字段,那么該參數(shù)的類型必然和這個字段相同,故而不必使用類型注解。

class Point {    // good
  int x, y;
  Point(this.x, this.y);
}
class Point {    // bad
  int x, y;
  Point(int this.x, int this.y);
}

你應該避免在函數(shù)表達式中使用類型注解。

函數(shù)表達式的一大優(yōu)點就是它的簡潔性。如果一個函數(shù)復雜到需要注解類型來理解它,它就應該是一個函數(shù)語句或者是一個方法。相應的,如果一個函數(shù)簡潔到可以作為一個表達式,那么它就不需要類型注解。

var names = people.map((person) => person.name);    // good
var names = people.map((Person person) {    // bad
  return person.name;
});

應當避免在不需要的時候使用 dynamic 來添加類型注解。

在 Dart 中,多數(shù)情況下類型注解都是可以忽略的,因為它們會被自動當做 dynamic 類型。所以,不添加類型注解在語義上是完全沒問題的,并且代碼會顯得更簡潔。

lookUpOrDefault(String name, Map map, defaultValue) {    // good
  var value = map[name];
  if (value != null) return value;
  return defaultValue;
}
dynamic lookUpOrDefault(String name, Map map, dynamic defaultValue) {    // bad
  var value = map[name];
  if (value != null) return value;
  return defaultValue;
}

對于接收的任何對象,應該使用 Object 代替 dynamic 來表明參數(shù)是對象。

有些操作可能對于任何對象都適用。比如,toString() 用于輸出信息,并且可以用于任何對象。在 Dart 中有兩種類型可以匹配所有對象:Object 以及 dynamic。但是,它們表示的是兩種不同的東西。

Object 注解表明 “我可以接收任何對象,只要它含有相關對象自身定義的方法?!?/p>

dynamic 類型注解表明沒有注解可以說明你實際允許的對象是什么類型。(也可能有,但是你不在意是否要聲明)

//good
// Accepts any object.
void log(Object object) {
  print(object.toString());
}

// Only accepts bool or String, which can't be expressed in a type annotation.
bool convertToBool(arg) {
  if (arg is bool) return arg;
  if (arg is String) return arg == 'true';
  throw new ArgumentError('Cannot convert $arg to a bool.');
}
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號