Dartの名前付きコンストラクタの便利な使い方

プログラミング

はじめに

Dartの名前付きコンストラクタは、異なる初期化パターンを提供するための強力な機能です。ここでは、名前付きコンストラクタの便利な使い方について、備忘録として残しておきます。

オプション引数の指定

名前付きコンストラクタを使用して、オプション引数を指定することができます。これにより、異なるパラメーターを持つオブジェクトを簡単に生成することができます。

class Point {
  int x;
  int y;

  Point(this.x, this.y);

  Point.origin() : this(0, 0);
}

void main() {
  var p1 = Point(10, 20);
  var p2 = Point.origin();

  print('p1: (${p1.x}, ${p1.y})'); // p1: (10, 20)
  print('p2: (${p2.x}, ${p2.y})'); // p2: (0, 0)
}

Dart

ファクトリメソッドの代替

名前付きコンストラクタは、ファクトリメソッドの代わりとして使用することもできます。ファクトリメソッドは、新しいインスタンスを作成するための静的メソッドですが、名前付きコンストラクタを使用することで、より自然に新しいインスタンスを生成することができます。

class Logger {
  final String name;
  static final Map<String, Logger> _cache = {};

  factory Logger(String name) {
    return _cache.putIfAbsent(name, () => Logger._internal(name));
  }

  Logger._internal(this.name);

  void log(String message) {
    print('$name: $message');
  }
}

void main() {
  var logger1 = Logger('Logger1');
  var logger2 = Logger('Logger1');
  var logger3 = Logger('Logger2');

  print(logger1 == logger2); // true (同じインスタンス)
  print(logger1 == logger3); // false (異なるインスタンス)
}

Dart

_internal() としている箇所は、コンストラクタをプライベートアクセスにしている部分です。 _internal() という名前は慣例的なものであって、必ずしもこの名前である必要はありません。極端な話 _() などでも構いませんが、慣例に従う方が混乱を避けるためには良いでしょう。

クラスの機能の明示化

名前付きコンストラクタを使用することで、クラスの機能を明示的に示すことができます。特定の初期化方法を示す名前付きコンストラクタを提供することで、クラスの振る舞いを理解しやすくなります。

class DatabaseConnection {
  final String connectionString;

  DatabaseConnection(this.connectionString);

  DatabaseConnection.fromConfigFile(String filename) {
    // ファイルから設定を読み込んで、connectionStringを初期化する処理
  }
}

void main() {
  var db1 = DatabaseConnection('mysql://localhost:3306/mydb');
  var db2 = DatabaseConnection.fromConfigFile('config.ini');
}
Dart

まとめ

名前付きコンストラクタは、Dartでクラスの初期化パターンを柔軟に指定するための強力なツールです。オプション引数の指定やファクトリメソッドの代替として利用することで、コードの可読性や保守性を向上させることができ、クラスの機能を明示化するためにも役立ちます。

タイトルとURLをコピーしました