👋

Dart NamedConstructorsを公式ドキュメントに基づいて調査する

2024/11/11に公開

https://dart.dev/language/constructors#named-constructors

前提

実務でNamedConstructorを見かけたが何をやっているかイマイチわからなかったので、公式ドキュメントに基づいて調査する。
個人的な目標は、種類の多いコンストラクタを理解しつつ、シングルトンパターンのコードを説明可能な状態にする。
最適な使い方や応用例は今後の実務コードやOSSのコードを読んで探ろうと思うので触れず、あくまで使い方と仕様にフォーカスする。

名前付きコンストラクタとは

Use a named constructor to implement multiple constructors for a class or to provide extra clarity:
名前付きコンストラクタを使用して、クラスに複数のコンストラクタを実装したり、明確さを高めたりします

サンプルコード

const double xOrigin = 30;
const double yOrigin = 70;

class PointWithNameConstructor {
  final double x;
  final double y;

  PointWithNameConstructor(this.x, this.y);

  // Named constructor
  PointWithNameConstructor.origin()
      : x = xOrigin,
        y = yOrigin;
}

void main() {
   final point = PointWithNameConstructor.origin();
  print('${point.x},${point.y}');
}

出力結果


30,70

注意点

1. サブクラスが親クラスの名前付きコンストラクタを継承しない

こちらもドキュメント参照

A subclass doesn't inherit a superclass's named constructor. To create a subclass with a named constructor defined in the superclass, implement that constructor in the subclass.
サブクラス[1]はスーパークラス[2]の名前付きコンストラクターを継承しません。スーパークラスで定義された名前付きコンストラクターを持つサブクラスを作成するには、そのコンストラクターをサブクラスで実装します。

つまり以下のような使い方は出来ない。

const double xOrigin = 30;
const double yOrigin = 70;

class SuperPointWithNameConstructor {
  final double x;
  final double y;
  SuperPointWithNameConstructor(this.x, this.y);
  SuperPointWithNameConstructor.origin()
      : x = xOrigin,
        y = yOrigin;
}

class SubPointWithNameConstructor extends SuperPointWithNameConstructor {
  SubPointWithNameConstructor();
}

void main() {
  final point = SubPointWithNameConstructor.origin(); // originメソッドが存在しないと怒られる
  print('${point.x},${point.y}');
}

2. 一部だけパラメータを変更したい場合

リダイレクトコンストラクタを使う。

まとめ

  • 名前付きコンストラクタを用いることによって、クラスに複数のコンストラクタを実装できる。

OSSで名前付きコンストラクタを使用していた箇所

video_playerのVideoPlayerControllerの定義箇所

https://github.com/flutter/packages/blob/main/packages/video_player/video_player/lib/video_player.dart#L267-L303

その他参考記事

https://dev.classmethod.jp/articles/about_dart_constructors/#item_01-02

脚注
  1. 親クラス(スーパークラス)の継承先のこと ↩︎

  2. サブクラスの継承元のこと ↩︎

Discussion