最常見的構造函數形式,即生成構造函數,創建一個類的新實例:
class Point {
num x, y; //Dart中int和double是num的子類
//this引用當前類對象
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
使用語法糖的時候可以這樣定義:
class Point {
num x, y;
//用於設置x和y的語法糖
//在構造函數體運行之前
Point(this.x, this.y);
@override
String toString() {
return ("x: $x, y: $y");
}
}
//print(new Point(100, 200)); -> 打印 x: 100, y: 200
默認構造函數
如果未聲明構造函數,則會提供默認構造函數。 默認構造函數沒有參數,並在調用父類無參數構造函數。
class Parent{
Parent(){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(){
print('In Child\'s constructor.');
}
}
//new Child(); -> 打印 In Parent's constructor. In Child's constructor.
構造函數不能繼承
子類不能繼承其父類構造函數,一個沒有聲明構造函數的子類只有默認(無參數,無名稱)構造函數
命名構造函數
當我們需要定義一個有特別含義的構造函數的時候,可以通過構造函數.XXX來命名構造函數
class Point{
num x;
num y;
Point(this.x, this.y);
//創建一個座標原點類
Point.origin(){
this.x = 0;
this.y = 0;
}
//創建一個座標爲(100, 100)的類
Point.coordinate100(){
this.x = 100;
this.y = 100;
}
@override
String toString() {
return ("x: $x, y: $y");
}
}
調用父類構造函數
默認情況下,子類中的構造函數調用父類的未命名無參數構造函數。 父類的構造函數在子類構造函數體的開頭被調用。 如果還使用初始化了列表,則會在調用父類構造函數之前執行。 執行順序如下:
- 初始化列表
- 父類的無參數構造函數
- 子類的無參數構造函數
如果父類沒有未命名的無參數構造函數,則必須手動調用父類中的一個構造函數。 在子類的構造函數體之後用冒號(:)指定父類構造函數
例1:默認先調用父類的無參數構造函數
class Parent{
Parent(){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) {
print('In Child\'s constructor.');
}
}
//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.
例2:手動調用父類其他構造函數
class Parent{
num x;
num y;
Parent(this.x, this.y){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) : super(x, y){
print('In Child\'s constructor.');
}
}
//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.
關於初始化列表:
調用父類構造函數之前,可以在構造函數體執行之前初始化示例變量,用逗號分隔,該過程叫初始化列表。
class Parent{
num x;
num y;
num sum;
Parent(num px, num py) : x = px, y = py, sum = px + py{
print("x: $x, y: $y, sum: $sum");
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) : super(x, y){
print('In Child\'s constructor.');
}
}
// new Child(100, 100); -> 打印
//x: 100, y: 100, sum: 200
//In Parent's constructor.
//In Child's constructor.
重定向構造函數
有時構造函數需要重定向到同一個類中的另一個構造函數,在冒號後面用this:
class Point {
num x, y;
//類的主構造函數
Point(this.x, this.y);
//重定向到主構造函數
Point.alongXAxis(num x) : this(x, 0);
}
常量構造函數
如果你的類需要成爲永遠不會更改的對象,則可以使這些對象成爲編譯時常量。 定義const構造函數要確保所有實例變量都是final。
class Point {
final num x;
final num y;
static final Point2 origin = const Point2(0, 0);
//const關鍵字放在構造函數名稱之前,且不能有函數體
const Point2(this.x, this.y);
}
沒有定義final時提示:
使用函數體時提示:
工廠構造函數
在實現不用總是創建新的類對象的時候,可以使用factory關鍵字。 例如,工廠構造函數可能從緩存中返回實例,或者它可能返回子類型的實例:
class Logger {
final String name;
bool mute = false;
//工廠構造函數無法訪問this,所以這裏要用static
//維護一個緩存的Map對象,
static final Map<String, Logger> _cache =
<String, Logger>{};
//調用該構造函數的時候,會從Map中取出對象
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
//調用
var logger = Logger('UI');
logger.log('Button clicked');