基礎型#
先來最簡易的版本,不管從任何語言背景來的人都能看懂。
另外要注意在dart 2.0以後,new變成了可選字眼,所以為了程式簡潔,個人建議不要再加new。
class Cat{
int age;
Cat(int age){
this.age = age;
}
}
// 使用時
var cat = Cat(1);
// or 舊版寫法,2.0後亦相容。
var cat = new Cat(1);延伸一點,其實參數可以直接使用this.fieldName來進行初始化。
可以減少許多冗餘的程式碼。
class Cat{
int age;
Cat(this.age);
}
// 使用時
var cat = Cat(1);如果想在填參數時能夠直接參照fieldName,可以將參數用大括弧括起。
這種做法叫做 Optional named parameters,顧名思義,在初始化時甚至可以不給值。
class Cat{
int age;
Cat({this.age});
}
// 使用時
var cat = Cat(age=1);
// or 可以不給值
var cat = Cat();另外要注意constructor是不會繼承的,也就是繼承後的物件僅有default constructor。
Named constructors#
Dart是沒有function overloading的,所以若想擁有不同constructor,就需要對這些constructor進行命名。
class Cat{
int age;
Cat.baby(){
age = 0;
}
}
// 使用時
var babyCat = Cat.baby();另外如果想要給class field初始值,還有以下幾種方法
class Cat{
// 適用於有多個constructor又想指定為同一個初始值時
int age = 0;
Cat.baby();
}
class Cat{
// 適用於有多個constructor但想指定不同初始值時
int age;
Cat.baby(): age=0;
Cat.baby2(): age=0 {
//這裡還可以再加寫東西
};
}
class Cat{
// 適用於Optional named parameters
int age;
// 新版寫法
Cat.baby({this.age=0});
// 舊版寫法,可能會被廢棄,不再建議使用。
Cat.baby2({this.age:0});
}值得注意的是,如果field為final,則第一種(在大括號內初始化)的方法就不再適用,編譯器會報出錯誤訊息。
另外這些初始化方法不管是基礎型constructor或是Named constructor皆適用。
const constructor#
這是一個比較難懂的概念,可以先參看下列的範例。
class Cat{
final int age;
const Cat(this.age);
}
// 使用時
var a = const Cat(1);
var b = const Cat(1);
assert(a == b); // true
// 錯誤使用
var c = Cat(1);
var d = Cat(1);
assert(c == d); // error簡單的說,a跟b為同樣的instance,所以在進行==比較時回傳結果為true。而c跟d為不同的instance,在進行比較時回傳結果為false。
a跟b明明都是由constructor所產生,但卻產生了一樣的instance,因此這個constructor被稱為const constructor。
現在我們來看一下要使用const constructor的規則。
- class內的所有成員皆為final。
- 被宣告為const的constructor一定要初始化所有變數。
- 要使用const constructor時,必須明確的在constructor前再次加上const。(e.g.
var cat = const Cat(1);) - 使用const constructor時,所有傳入的參數必須要是常數(constant),否則編譯器會報錯。
- 若使用const constructor時沒加上const前綴,也可以當作一般的constructor用。(e.g.
var cat = Cat(1);)
因此宣告ㄧ個const constructor,並不代表使用這個constructor的結果都為const constructor,這是最大的陷阱。
下面再多給幾個範例。
// 可行,傳入變數為constant
const a = 1;
var cat = const Cat(a);
// 不可行,final並非constant
final a = 1;
var cat = const Cat(a); // error
// 可行,不加上const前綴則當作一般的constructor
final a = 1;
var cat = Cat(a);factory constructor#
最後一個要提的constructor是factory constructor,顧名思義,此為factory pattern的語法糖。
class Cat{
int age;
factory Cat.baby(){
final cat = Cat();
cat.age = 0;
return cat;
}
}
// 使用時
var cat = Cat.baby();這個範例可以很清楚的看到,factory constructor的instance製造是仰賴其他constructor,而且最後還必須return instance。
所以factory constructor根本不是constructor,而是一個factory,只是用個語法糖讓他看起來像constructor罷了。
