dart 構造函數 ClassName(...) //普通構造函數 普通構造函數 這就是我們普通的構造函數,其樣子和其它語言幾乎一樣 class Point { num x, y; Point(num x, num y) { // There's a better way to do this, stay tuned. this.x = x; this.y = y; } } 上例中只有兩個成員變量,如果有10個,豈不是麻煩死?所以Dart有語法糖給你哦: class Point { num x, y; // Syntactic sugar for setting x and y // before the constructor body runs. Point(this.x, this.y); } 它可以將x,y的賦值變得簡單一些,就不用寫構造函數的方法體了,記得括號后用分號哦。 Classname.identifier(...) //命名構造函數 命名構造函數 class Point { num x, y; Point(this.x, this.y); // 命名構造函數,新增代碼 Point.origin() { x = 0; y = 0; } } 請記住,命名構造函數不可繼承,如果子類想要有 和父類一樣的命名構造函數,那就寫個同名的(通常也會在子類的命名構造函數里,調用父類的同名命名構造函數) const ClassName(...) //常量構造函數 常量構造函數總結如下幾點: 常量構造函數需以const關鍵字修飾 const構造函數必須用於成員變量都是final的類 構建常量實例必須使用定義的常量構造函數 如果實例化時不加const修飾符,即使調用的是常量構造函數,實例化的對象也不是常量實例 下面結合實例,對以上幾點加以說明 正確的常量構造函數定義 根據以上的總結,定義一個Point類,包含一個常量構造函數,注意其成員變量都是final類型,且構造函數用const修飾 class Point { final int x; final int y; const Point(this.x, this.y); } 常量構造函數需以const關鍵字修飾 如下代碼定義一個const對象,但是調用的構造方法不是const修飾的,則會報The constructor being called isn't a const constructor.錯誤 void main() { const point = Point(1, 2); // 報錯 } class Point { final int x; final int y; Point(this.x, this.y); } const構造函數必須用於成員變量都是final的類 如下代碼中成員變量x為非final,會報Can't define a const constructor for a class with non-final fields.錯誤 class Point { int x; final int y; const Point(this.x, this.y); } 構建常量實例必須使用定義的常量構造函數 如下代碼,定義一個const對象,但是調用的卻是非常量構造函數,會報The constructor being called isn't a const constructor.錯誤 void main() { var point = const Point(1, 2); // 報錯 print(point.toString()); } class Point { int x; int y; Point(this.x, this.y); // 非const構造函數 String toString() { return 'Point(${x}, ${y})'; } } 如果實例化時不加const修飾符,即使調用的是常量構造函數,實例化的對象也不是常量實例 如下代碼,用常量構造函數構造一個對象,但是未用const修飾,那么該對象就不是const常量,其值可以再改變 void main() { var point = Point(1, 2); // 調用常量構造函數,但是未定義成常量 print(point.toString()); point = Point(10, 20); // 可以重新賦值,說明定義的變量為非常量 print(point.toString()); } class Point { final int x; final int y; const Point(this.x, this.y); String toString() { return 'Point(${x}, ${y})'; } } factroy ClassName(...) //工廠構造函數 工廠構造函數的定義 工廠構造函數是一種構造函數,與普通構造函數不同,工廠函數不會自動生成實例,而是通過代碼來決定返回的實例對象. 工廠構造函數的關鍵字為factory,下面我們用工廠構造函數寫一個只能創造一個實例的類. class A{ String name; static A cache; factory A([String name='A']){ if(A.cache===null){ A.cache=new A.newObject(name); } return A.cache; } A.newObject(this.name); } void main(){ A a=new A('HelloWorld'); print(a.name); A b=new A('HelloDart'); print(b.name); print(a===b); } A類具有一個名為cache的靜態成員,它將緩存A類的第一個實例. 在工廠構造函數A中,首先判斷A.cache是否已經存在實例(即判斷是否是第一次實例化),如果存在則返回緩存的實例,不存在則新建一個實例並緩存. A.newObject是一個命名構造函數,用於創建實例. 運行這段代碼,會輸出 HelloWorld HelloWorld true 其中字符串”HelloWorld”是第一個實例的name成員,在聲明變量b時改用了”HelloDart”,但返回的實例的name成員仍然是”HelloWorld”. 再用===運算符判斷一下它們是否屬於同一個對象,結果為true,變量a和b指向的是同一個對象. 3.8.2 工廠構造函數的特性 工廠構造函數類似於static靜態成員,無法訪問this指針,所以在工廠構造函數中能處理的任務較為有限. 使用工廠構造函數時往往需要定義一個命名構造函數用來生產實例. 注意點 初始化列表 初始化列表的執行順序,在整個構造函數的最前面,它除了可以調用父類的構造函數,還可以在構造函數方法體之前,初始化一些成員變量。 // Initializer list sets instance variables before // the constructor body runs. Point.fromJson(Map<String, num> json) : x = json['x'], y = json['y'] { print('In Point.fromJson(): ($x, $y)'); } 尤其是初始化那些final修飾的成員變量時,初始化列表很有用,因為在方法體中,不能給final修飾的成員變量賦值,因為在執行方法體的時候,final修飾的成員變量已經不能變了。這個地方很多人犯錯。 import 'dart:math'; class Point { final num x; final num y; final num distanceFromOrigin; Point(x, y) : x = x, y = y, distanceFromOrigin = sqrt(x * x + y * y); } main() { var p = new Point(2, 3); print(p.distanceFromOrigin); } 參考: 鏈接:https://www.jianshu.com/p/a0ba5f2ac5ce