簡介
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/
最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!
