簡介
dart作為一種物件導向的語言,class是必不可少的。dart中所有的class,除了Null都繼承自Object class。 要想使用dart中的類就要構造類的例項,在dart中,一個類的建構函式有兩種方式,一起來看看吧。
傳統的建構函式
和JAVA一樣,dart中可以使用和class名稱相同的函式作為其建構函式,這也是很多程式語言中首先的建構函式的建立方式,我們以Student類為例,來看看dart中的建構函式是怎麼樣的:
class Student {
int age = 0;
int id = 0;
Point(int age, int id) {
this.age = age;
this.id = id;
}
}
上面的this表示的是當前類的例項,對dart來說,this是可以忽略的,但是在上面的例子中,因為類變數的名字和建構函式傳入引數的名字是一樣的,所以需要加上this來進行區分。
上面的程式碼雖然很簡單,但是寫起來還是有太多的內容,下面是dart中的一種簡寫方式:
class Student {
int age = 0;
int id = 0;
Student(this.age, this.id);
}
當然,你也可以不指定建構函式,這樣的話dart會為你建立一個預設的無參的建構函式。
命名建構函式
dart和其他語言不同的地方是,還可以使用命名建構函式。命名建構函式的格式是ClassName.identifier,如下所示:
class Student {
int age = 0;
int id = 0;
Student(this.age, this.id);
Student.fromJson(Map data) {
print('in Student');
}
}
上面的Student.fromJson就是一個命名建構函式。可以使用該建構函式從Map中生成一個Student物件,有點像是java中的工廠方法。
建構函式的執行順序
我們知道,dart中的類是可以繼承的,那麼對於dart中的子類來說,其建構函式的執行順序是怎麼樣的呢?
如果不給dart類指定建構函式,那麼dart會為類自動生成一個無參的建構函式,如果這個類是子類的話,則會自動呼叫父類的無參建構函式。
那麼對應子類的建構函式來說,初始化的時候有三步:
- 呼叫初始化列表
- 呼叫父類的建構函式
- 呼叫自己的建構函式
在步驟2中,如果父類沒有預設的無參建構函式,則需要手動指定具體父類的建構函式。怎麼呼叫呢?可以直接在子類的建構函式後面使用:操作符接父類的建構函式,如下所示:
class Student {
String? firstName;
Student.fromJson(Map data) {
print('in Student');
}
}
class Jone extends Student {
Jone.fromJson(Map data) : super.fromJson(data) {
print('in Jone');
}
}
理解了父類的建構函式之後,我們再看一下什麼是初始化列表呢?
初始化列表就是在建構函式執行之前執行的程式碼,和呼叫父類的建構函式一樣,也使用:操作符,如下所示:
Point.fromJson(Map<String, double> json)
: x = json['x']!,
y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
重定向建構函式
如果一個建構函式需要呼叫另外一個建構函式,而其本身並不進行任何變動,這可以使用重定向建構函式,重定向建構函式也使用:操作符,後面跟的是另外的建構函式:
class Point {
double x, y;
// 主建構函式
Point(this.x, this.y);
// 重定向建構函式
Point.alongXAxis(double x) : this(x, 0);
}
Constant建構函式
如果物件中的屬性在建立之後,是不會變化的,則可以使用Constant建構函式, 也就是在建構函式前面加上const修飾符,初始化的所有屬性都要以final來修飾:
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0);
final double x, y;
const ImmutablePoint(this.x, this.y);
}
工廠建構函式
預設情況下,dart類中的建構函式返回的是該類的新例項,但是我們在實際的應用中可能會對返回的物件做些選擇,比如從快取中返回已經存在的物件,或者返回該類具體的實現子類。
為了實現這樣的功能,dart中專門有一個Factory關鍵字,使用Factory的建構函式叫做工廠建構函式。
class Student {
final String name;
static final Map<String, Student> _studentMap =
<String, Student>{};
factory Student(String name) {
return _studentMap.putIfAbsent(
name, () => Student._newStudent(name));
}
factory Student.fromJson(Map<String, Object> json) {
return Student(json['name'].toString());
}
Student._newStudent(this.name);
}
注意,dart中只能有一個未命名的建構函式,對應命名函式來說,名字不能夠重複,否則會報The default constructor is already defined異常。
上面的程式碼中,factory Student是一個未命名建構函式,而factory Student.fromJson則是一個命名建構函式。
所以如果你再給Student加一個未命名建構函式,如下:
Student(this.name);
則會報錯。
那麼問題來了,factory建構函式和普通建構函式到底有什麼區別呢?
他們最大的區別就是普通建構函式是沒有返回值的,而factory建構函式需要一個返回值。
總結
以上就是dart中各種建構函式,和使用過程中需要注意的問題。
本文已收錄於 http://www.flydean.com/06-dart-class/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!