surga Lab

開発したい!!

Flutter/Dart サンプルコードのコンストラクタでは何をやっているのか

Flutterの勉強を始めると下記のようなコードをよく見ると思います。
プロジェクトを新規作成した時のサンプルコードも同じ書き方ですね。

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

その中のここのコードについて

MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

なんとなく「StatefulWidget / StatelessWidgetのサブクラスを作成する時のコンストラクタなんだな」まではわかると思いますが、Dartに慣れていないと何をやっているかわかりませんでした。

Dartの記法

まずはDartの書き方について調べてみます。

生成的コンストラクタ

一般的なものです。newで生成する時の話です。

もちろん引数を指定することができます。

class Foo {
  final String title;
  Foo(title) {
  this.title = title
  }
}
var foo = new Foo('piyo');

Automatic field initialization

コンストラクタでthis.フィールド名とすれば、代入処理を書かなくても自動で代入してくれます。

下記の例では、titleの初期化を記述しなくても自動で代入しています。

class Foo {
  final String title;
  Foo(this.title);
}
var foo = new Foo('piyo')

名前付き引数

関数を呼ぶときは{}で囲むことにより、名前付きで指定することができます。コンストラクタでも同じです。

void foo({String title, String subtitle}) {
}
foo(title: 'titleA', subtitle: 'subtitleB');

なお、名前付き引数は呼び出し時に必須ではありません。

void foo({String title, String subtitle}) {
}
foo(title: 'titleA'); // subtitleは省略可能

Redirecting Constructors

コンストラクタの後に:をつけて他のコンストラクタを指定することでリダイレクトすることができます。

class Foo {
  Foo() : this.test();
  Foo.test() {
    print('test');
  }
}

Flutterのコンストラクタに当てはめる

上記を元に、Flutterのサンプルアプリを確認しましょう。

// 省略
MyHomePage(title: 'Flutter Demo Home Page')
// 省略

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, String title}) {
    this.title = title;
  }
  String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

引数は名前付きで指定されています。
Automatic field initializationも利用しています。

また、:super()でsuperクラスのコンストラクタへリダイレクトしています。

Keyは指定していませんが、「名前付き引数」では「全ての引数を指定すること」が必須でありません。

MyHomePage({Key key, this.title}) : super(key: key);
final String title;

super()を無視するならば、こんな感じに書き換えることもできます。
しかしこの方法ではfinalな値を書き換えることはできませんので注意してください。

class MyHomePage extends StatefulWidget {
  MyHomePage(title) {
    this.title = title;
  }
  String title;

What's Key?

ここで気になるのが「Keyとは何か」です。

一番わかりやすいのが下記の動画です。

www.youtube.com

使い所は多くはありませんが、、
例えばTODOリストでは、優先順位を表すためにタイルウィジェットに対して順序変更、削除、追加などを行います。
その際、古いステートを取得することを防ぐために便利です。

Keyの説明は本記事の主題と少し異なるため、いずれ別記事として書くかもしれません。

今回の主題である「サンプルアプリのコンストラクタでは何をやっているか」ですが、
サンプルアプリ上ではKeyは指定していないので(名前付き引数は省略可能)、
結果として特に何もしていないことがわかります。

参考にさせていただいたサイト

Dartのコンストラクタについて | DevelopersIO

flutter MyhomePage({Key key, this.title}) : super(key: key); pls any one explain clearly with example flutter - Stack Overflow

When to Use Keys - Flutter Widgets 101 Ep. 4 - YouTube

Dartでfinalなメンバ変数を初期化する方法のまとめ