名前付きコンストラクタのメリット

突然ですが、宣伝。
Dart普及の一環として、Nagoya.dartという勉強会を開催します。

5人以上は集めて、nagoya.phpを越したいところ。

そもそもの知名度が低い上に、当日までの宣伝の機会があまり無く、
さらに愛知県開催1というのが危機感を煽っております。
が、Dartについてまとまって語れるチャンスはそうそう無いので、非常に楽しみです。

さて、今回は他の言語では中々見られない、名前付きコンストラクタ(Named Constructor)についてです。
簡単な説明から始めて、これが何故必要なのか、どのようなメリットがあるのかを見ていきましょう。

定義と使い方

名前付きコンストラクタの簡単な例を示します。まずは定義から。

class Point{
  final num x;
  final num y;
  // 普通のコンストラクタ定義
  Point(this.x, this.y);
  // 以下2つは名前付きコンストラクタ定義
  Point.zero() : this.x = 0, this.y = 0;
  Point.copy(Point original) : this.x = original.x, this.y = original.y;
}

下記の式は全て、上記のコンストラクタを呼び出しています。
これらをオブジェクト生成式と言うこともあります。

  var p1 = new Point(1, 2);
  var p2 = new Point.zero();
  var p3 = new Point.copy(p1);

GoFデザインパターンの一つであるFactory Methodや、
C++イディオムの名前付きコンストラクタと似ていますが、
以下のような違いがあります。

  • 定義する側 : そのコンストラクタを定義しているクラスしか生成できない
  • 使用する側 : newキーワードを使用しないと呼び出せない

必要性

なぜDartには名前付きコンストラクタが必要なのか。

まず1つ目として、DartのOptional Typingは実行時に型情報が振る舞いに影響を与えないため、
関数やメソッドなどをオーバーロードして定義することができません
よって、関数名やメソッド名を変えることでしか別の関数・メソッドを定義できません。
これは、コンストラクタも同様で、複数のコンストラクタを定義するためには
名前によってコンストラクタを区別する方法が必要だったわけです。2

2つ目に、可視性の指定方法。
Dartのクラスやメソッドなどの可視性は、
publiclibrary privateの2種類があります。
デフォルトの可視性はpublic
クラスやメソッド名の頭文字を_(アンダースコア)にするとlibrary privateになります。
つまりDartでは可視性を名前で指定します。
コンストラクタの可視性も同様に名前で指定する必要があります。

メリット

主に言語の一貫性という観点から、名前付きコンストラクタという仕様が生まれたのでしょう。
Dartの言語設計者は、言語仕様のシンプルさを保つことを非常に重要視しています。

オーバーロードができない、というのは賛否両論あると思いますが
「引数の型のみで意図の違いを伝えられる関数・メソッド・コンストラクタを定義することは
意外と難しい」と考えているので、
自分にとってはあまり気になりません。

また、Factory MethodパターンやC++の名前付きコンストラクタのイディオムなどは
各々のメソッドの仕様を理解していないと、
それを用いた式が新しいオブジェクトを生成する式であることを理解できません。3

Dartの名前付きコンストラクタの場合、 newキーワードを使用するため、
その式が新しいオブジェクトを生成する式であることが容易に理解できます。
DartEditorなどの、Syntax highlightをサポートしているツールを用いれば、さらに可読性が高くなります。

まとめ

  • 名前付きコンストラクタは、オブジェクト生成式であることを自明にする
  • オーバーロードできない代わりに、名前で意図を伝えよう

・・・この仕様も、他の言語にも欲しいですね。特に動的なオブジェクト指向言語では。


  1. Nagoyaと冠しているのに、名古屋市ではなく大府市開催という罠。場所取りに苦労したんです・・・ 

  2. RubyやPythonなどの動的言語では、Dartと同様オーバーロードできませんが、コンストラクタに任意の名前を付けられないため複数のコンストラクタを定義できません 

  3. 大半の方がメソッドの「名前」で表現するとは思いますが 

このエントリーをはてなブックマークに追加
comments powered by Disqus