【 Flutter 】Flutter を 基礎 から 学習 ( Dart編 ) part22 コンストラクタ

基礎 から 学ぶ Flutter 」という書籍で  学習 したことを ブログでアウトプットしていこうと思います。今回は Dart編 ( part22 )です

前回

【 Flutter 】Flutter を 基礎 から 学習 ( Dart編 ) part21 コンストラクタ

今回もコンストラクタの学習です。

コンストラクタ

Redirecting constructors

他のコンストラクタを呼び出したい場合はRedirecting constructorsという機能をしようするようです。
前回のinitializer list同様にコロン:の後ろに記述します。
・・・このコロン:はいろんな機能で使用するわけですね。

class Hoge {
  String name = '';
  num age = 0;
  Hoge() {
    age = 20;
  }
  // Redirect constructorsの機能を使用する場合はボディ(実装)を持つことはできないようです。
  // 以下の実装はコンパイルエラーです。
  //Hoge.name(String value) : this() {
  //  print('継承元 :引数あり・・・$value');
  //}
  
  Hoge.name(String value) : this();
}

void main() {
  var a = Hoge.name('太郎'); 
}

この機能を使用する場合は実装を持ってはいけないようです。
本書でも「本文は空にして」という記載があります。

Constant constructors

生成後変更できないオブジェクトを生成する場合はConstant constructorsという機能を使います。
Value Objectという言葉を聞いたことがありますがこのことですかね。

コンストラクタの修飾子としてconstキーワードを使用します。
フィールドはfinalで修飾します。

class Hoge {
  // フィールドは必ずfinalで修飾する必要があります。
  final String name; // 初期化するとコンストラクタの部分でコンパイルエラーになります
  final num age;
  
  
  const Hoge(this.name, this.age);
}

void main() {
  // 使う側もconstで修飾しないとConstant constructorsが成り立たないようです。
  const Hoge a = Hoge('太郎', 20);

  // 再代入不可なので以下の実装はコンパイルエラーです。
  //a = Hoge('次郎', 20);
  //a.name = 'test';
}

Factory constructors

DartではFactoryパターンが言語レベルで組み込まれています。
Factoryパターンについてはこちらの記事が参考になりました。

デザインパターン「Factory Method」 – Qiita

本書は「シングルトンパターン」の説明のように見えるのですが・・・。
キャッシュでFactoryパターンを使うことはあまりないようにおもいます。

class Logger {
  final String name;
  bool mute = false;
  
  static final Map<String, Logger> _cache = <String, Logger>{};
  
  factory Logger(String name) {
    if(_cache.containsKey(name)) {
      // Loggerではなく「Logger?」が返却されるようになった(おそらくDart v2.12で実装されたNullセーフのせい)ので、
      // 本書の実装ではコンパイルエラーとなります。
      //return _cache[name];
      
      // キャストするしかなかでしょうか?
      return _cache[name] as Logger;
    } else {
      // named construcorsを呼び出します。
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }
  
  // named constructorsですね。
  Logger._internal(this.name);
  
  void log(String msg) {
    if(!mute) print(msg);
  }
}

void main() {
  var logger01 = Logger('hoge');

  var logger02 = Logger('hoge');
  
  if(logger01 == logger02) {
    print('同じオブジェクト');
  } else {
    print('違うオブジェクト');
  }
}

最後に

Dartではさまざまなコンストラクタが用意されていることがわかりました。
使いどころがパっと思いつきませんがFlutterではこのあたりの機能を多用しているのだと想像します!

今日はここまで!