flutterのコンストラクタ種類多すぎるやろ...
そんなとき、めちゃくちゃわかりやすい記事に出会いました。
今回はその記事を参考に私の考えを整理していきたいと思います。
こちらは一般的なコンストラクタです。new
演算子を使うことでコンストラクタを起動することができます。
実際にコードを見てみましょう!
以下のコードがクラスの実装のコードです。引数を指定しないタイプのコンストラクタを実装します。
class Human {
var name;
Human(){
this.name = "Anonymous";
}
}
クラスからインスタンスを作成してみましょう!
// main関数の中でインスタンスを作成するコードを書いていく
main(){
var human = new Human();
print(human.name);
}
コンソール画面
Anonymous
引数を指定するタイプのコンストラクタを持つクラスを作成してみましょう!
void main() {
// Humanクラスのコンストラクタの実行(引数に"Junki"を渡す)
var human = new Human("Junki");
print(human.name);
}
class Human {
var name;
Human(name){
this.name = name;
}
}
コンソール画面
Junki
以上が基本的なコンストラクタの実装になります。
先程説明した引数を受け取るタイプのコンストラクタについてですが、引数で受け取った値をわざわざthis.name
に代入するようにコードを書く必要があります。これめんどくさいですよね...。
その問題を解決するのがAutomatic field initializationになります。Constructor(this.fieldname)
のように書くことで自動的にメンバ変数のnameに引数のnameの値を渡してくれます。便利〜。
実際のコードをいかに示します
void main() {
// Humanクラスのコンストラクタの実行
var human = new Human("Automatic man");
print(human.name);
}
class Human {
var name;
// Automatic field initializationコンストラクタの定義
Human(this.name);
}
コンソール画面
Automatic man
名前付きコンストラクタは、その名の通りコンストラクタに対して名前をつけることが可能です。Constructors.name()
のように書くことで実装することができます。
イメージとしては、コンストラクタをオーバーロードする感じです。
実際にコードを見てみましょう。
void main() {
// Humanクラスのコンストラクタの実行
var human = new Human();
var junki = new Human.name("Junki");
print(human.name);
print(junki.name);
}
class Human {
var name;
// 一般的なコンストラクタ
Human(){
this.name = "Anonymous";
}
// 名前付きコンストラクタ
Human.name(this.name);
}
コンソール画面
Anonymous
Junki
起動させるコンストラクタを指定することができる記述方法です。コンストラクタの後に:
に続いて起動させたいコンストラクタを指定することができます。
void main() {
// Humanクラスのコンストラクタの実行
var human = new Human();
var junki = new Human.name("Junki");
print(human.name);
print(junki.name);
}
class Human {
var name;
// リダイレクトする
Human():this.anonymous();
// 名前付きコンストラクタ(匿名版)
Human.anonymous(){
this.name = "Anonymous";
}
// 名前付きコンストラクタ
Human.name(this.name);
}
コンソール画面
Anonymous
Junki
リダイレクト元のコンストラクタに処理を定義することが可能です(マージの挙動)。
この場合、リダイレクト先のコンストラクタが先に走って、その後リダイレクト元のコンストラクタが走るようです。
具体的なユースケースとして、クラス継承時に親クラスのコンストラクタをオーバーライドする際にリダイレクティングコンストラクタを使用すると思います。
実際にコードを見てみましょう。
// main関数(ビルド時に走る関数)
void main(){
final junki = new Junki("junki",20);
print("My name is " + junki.name);
print(junki.age);
}
// 親クラスの定義
class Human {
// member variable
var name;
// constructor
Human(name) {
this.name = name;
}
}
// 継承クラスの定義
class Junki extends Human {
var name;
var age;
// 親クラスのコンストラクタをリダイレクト
Junki(name,age):super(name){
this.age = age;
}
}
コンソール画面
My name is junki
20
コンストラクタの後に:
に続けてフィールドの初期化処理を記述していくようです。
これで書くぐらいなら、普通のコンストラクタで書いたほうがわかりやすいのではないかと思いました。
実際にコードを見てみまましょう。
void main() {
final human1 = new Human.initializerList("name1",1);
print(human1.name);
print(human1.age);
print("---------------------------");
final human2 = new Human.normal("name2",2);
print(human2.name);
print(human2.age);
}
class Human {
// member variables
var name;
var age;
// constructor(initializer lists)
Human.initializerList(name,age): this.name = name,
this.age = age;
// normal constructor
Human.normal(name,age) {
this.name = name;
this.age = age;
}
}
コンソール画面
name1
1
---------------------------
name2
2
以下のように書くことでプロパティ初期化子のような機能を持たせることができます。
void main() {
final human = new Human("banana");
print(human.name);
print(human.age);
print(human.food);
}
class Human {
// member variables
var name;
var age;
var food;
// constructor
Human(this.food) : this.name = "Anonymous",
this.age = 0;
}
コンソール画面
Anonymous
0
banana
おつです。
参考にした記事のリンクを以下に載せておきます。
Dartのコンストラクタについて | DevelopersIO
https://dev.classmethod.jp/articles/about_dart_constructors/