程式碼規範
順序
為了使檔案前面部分保持整潔,我們規定了關鍵字出現順序的規則。每個“部分”應該使用空行分割。
要把 “dart:” 匯入語句放到其他匯入語句之前。
要把 “package:” 匯入語句放到專案相關匯入語句之前。
import 'dart:async';
import 'dart:html';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'util.dart';
複製程式碼
推薦 把外部擴充套件 “package:” 匯入語句放到其他語句之前。
如果你使用了多個 “package:” 匯入語句來匯入自己的包以及其他外部擴充套件包,推薦將自己的包分開放到一個額外的部分。
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'package:my_package/util.dart';
複製程式碼
要 把匯出(export)語句作為一個單獨的部分放到所有匯入語句之後。
import 'src/error.dart';
import 'src/foo_bar.dart';
export 'src/error.dart';
複製程式碼
變數
在 Dart 中,未初始化的變數擁有一個預設的初始化值:null。即便數字也是如此,因為在 Dart 中一切皆為物件,數字也不例外。
int lineCount;
assert(lineCount == null);
複製程式碼
var
在Dart中用var宣告一個變數後,Dart在編譯時會根據第一次賦值資料的型別來推斷其型別,編譯結束後其型別就已經被確定。
dynamic和Object
Object 是Dart所有物件的根基類,也就是說所有型別都是Object的子類(包括Function和Null),所以任何型別的資料都可以賦值給Object宣告的物件. dynamic與var一樣都是關鍵詞,宣告的變數可以賦值任意物件。 而dynamic與Object相同之處在於,他們宣告的變數可以在後期改變賦值型別。
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面程式碼沒有問題
t = 1000;
x = 1000;
複製程式碼
dynamic與Object不同的是,dynamic宣告的物件編譯器會提供所有可能的組合, 而Object宣告的物件只能使用Object的屬性與方法, 否則編譯器會報錯。
dynamic的這個特性與Objective-C中的id作用很像. dynamic的這個特點使得我們在使用它時需要格外注意,這很容易引入一個執行時錯誤.
final和const
如果您從未打算更改一個變數,那麼使用 final 或 const,不是var,也不是一個型別。 一個 final 變數只能被設定一次,兩者區別在於:const 變數是一個編譯時常量,final變數在第一次使用時被初始化。被final或者const修飾的變數,變數型別可以省略,如:
//可以省略String這個型別宣告
final str = "hi world";
//final String str = "hi world";
const str1 = "hi world";
//const String str1 = "hi world";
複製程式碼
函式
Dart是一種真正的物件導向的語言,所以即使是函式也是物件,並且有一個型別Function。這意味著函式可以賦值給變數或作為引數傳遞給其他函式,這是函數語言程式設計的典型特徵。
Dart函式宣告如果沒有顯式宣告返回值型別時會預設當做dynamic處理,注意,函式返回值沒有型別推斷。
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
typedef bool CALLBACK();
//不指定返回型別,此時預設為dynamic,不是bool
isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void test(CALLBACK cb){
print(cb());
}
//報錯,isNoble不是bool型別
test(isNoble);
複製程式碼
級聯運算子(..)
級聯運算子(..)可以讓你在同一個物件上連續呼叫多個物件的變數或方法。
比如下面的程式碼:
querySelector('#confirm') // 獲取物件 (Get an object).
..text = 'Confirm' // 使用物件的成員 (Use its members).
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
複製程式碼
第一個方法 querySelector 返回了一個 Selector 物件,後面的級聯操作符都是呼叫這個 Selector 物件的成員並忽略每個操作的返回值。
上面的程式碼相當於:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.lis
複製程式碼
ten((e) => window.alert('Confirmed!')); 級聯運算子可以巢狀,例如:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
複製程式碼
類
使用類的成員 物件的 成員 由函式和資料(即 方法 和 例項變數)組成。方法的 呼叫 要通過物件來完成,這種方式可以訪問物件的函式和資料。
使用(.)來訪問物件的例項變數或方法:
var p = Point(2, 2);
// 為例項變數 y 賦值。
p.y = 3;
// 獲取 y 的值。
assert(p.y == 3);
// 呼叫變數 p 的 distanceTo() 方法。
num distance = p.distanceTo(Point(4, 4));
複製程式碼
使用 ?. 代替 . 可以避免因為左邊表示式為 null 而導致的問題:
// If p is non-null, set its y value to 4.
// 如果 p 為非空則將其屬性 y 的值設為 4
p?.y = 4;
複製程式碼
使用建構函式 可以使用 建構函式 來建立一個物件。建構函式的命名方式可以為 類名 或 類名.識別符號 的形式。例如下述程式碼分別使用 Point() 和 Point.fromJson() 兩種構造器建立了 Point 物件:
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
複製程式碼
以下程式碼具有相同的效果,但是建構函式名前面的的 new 關鍵字是可選的:
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
複製程式碼
從 Dart 2 開始,new 關鍵字是可選的。
複製程式碼
獲取物件的型別 可以使用 Object 物件的 runtimeType 屬性在執行時獲取一個物件的型別,該物件型別是 Type 的例項。
print('The type of a is ${a.runtimeType}');
複製程式碼