Dart: コンストラクタの種類が多すぎる

Dart: コンストラクタの種類が多すぎる

August 18, 2024

公式ドキュメントの案内によると Dart のコンストラクタは6種類あるようです。

Dart implements many types of constructors. Except for default constructors, these functions use the same name as their class.

  • Generative constructors: Creates new instances and initializes instance variables.
  • Default constructors: Used to create a new instance when a constructor hasn’t been specified. It doesn’t take arguments and isn’t named.
  • Named constructors: Clarifies the purpose of a constructor or allows the creation of multiple constructors for the same class.
  • Constant constructors: Creates instances as compile-type constants.
  • Factory constructors: Either creates a new instance of a subtype or returns an existing instance from cache.
  • Redirecting constructor: Forwards calls to another constructor in the same class.

またコンストラクタと同等の動きをするものとして、インスタンスを返す static メソッドを実装することもできます。これらのコンストラクタを見ていきましょう。

class User {
  String name;
  int age;

  /// Generative constructors - 生成コンストラクタ
  ///
  /// いわゆる通常のコンストラクタ。
  User(this.name, this.age);

  /// Named constructors - 名前付きコンストラクタ
  ///
  /// 個別に名前をつけたコンストラクタ。
  User.named1(String name_, int age_)
      : name = name_,
        age = age_;
  User.named2({required name_, required age_})
      : name = name_,
        age = age_;
  User.named3({required this.name, required this.age});

  /// Redirecting constructors - リダイレクトコンストラクタ
  ///
  /// 他のコンストラクタを呼び出すコンストラクタ。
  User.redirect1(String name_, int age_) : this(name_, age_);
  User.redirect2(String name_, int age_) : this.named1(name_, age_);
  User.redirect3({required name_, required age_}) : this(name_, age_);
  User.redirect4({required name_, required age_}) : this.named1(name_, age_);

  /// Factory constructors - ファクトリコンストラクタ
  ///
  /// インスタンスを生成するメソッドを定義する。
  factory User.factory1(String name_, int age_) => User(name_, age_);
  factory User.factory2(String name_, int age_) => User.named1(name_, age_);
  factory User.factory3(String name_, int age_) => User.static1(name_, age_);
  factory User.factory4(String name_, int age_) = User;
  factory User.factory5({required name_, required age_}) => User(name_, age_);
  factory User.factory6({required name_, required age_}) => User.named1(name_, age_);
  factory User.factory7({required name_, required age_}) => User.static1(name_, age_);

  /// Static メソッドとしても実装可能
  static User static1(String name_, int age_) => User(name_, age_);
  static User static2(String name_, int age_) => User.named1(name_, age_);
  static User static3(String name_, int age_) => User.redirect1(name_, age_);
  static User static4(String name_, int age_) => User.factory1(name_, age_);
  static User static5({required name_, required age_}) => User(name_, age_);
  static User static6({required name_, required age_}) => User.named1(name_, age_);
  static User static7({required name_, required age_}) => User.redirect1(name_, age_);
  static User static8({required name_, required age_}) => User.factory1(name_, age_);
}

class UserConst {
  final String name;
  final int age;

  /// Const constructors - 定数コンストラクタ
  ///
  /// すべてのインスタンス変数が final の場合に const コンストラクタが宣言できる。
  const UserConst(this.name, this.age);
}

class UserDefault {
  /// Default constructors - デフォルトコンストラクタ
  ///
  /// コンストラクタを宣言しない場合、デフォルトコンストラクタが暗黙的に生成される。
}

// Generative constructors - 通常のコンストラクタ
final user1 = User('Alice', 10);
// Named constructors - 名前付きコンストラクタ
final user2 = User.named1('Bob', 20);
// Redirecting constructors - リダイレクトコンストラクタ
final user3 = User.redirect1('Charlie', 30);
// Factory constructors - ファクトリコンストラクタ
final user4 = User.factory1('Dave', 40);
// Static メソッド
final user5 = User.static1('Eve', 50);
// Const constructors - 定数コンストラクタ
const user6 = UserConst('Frank', 60);
// Default constructors - デフォルトコンストラクタ
final user7 = UserDefault();