コンストラクタに static 属性を指定した場合、そのコンストラクタは特別な静的コンストラクタとなります。 静的コンストラクタはインスタンス生成のための処理ではなく、クラスの静的メンバなどを初期化する一連のロジックを提供するために使われます。 このコンストラクタは new 演算子ではなく、プログラム起動時に main() 関数よりも先に呼び出されます。
static this() { 本文 }
静的コンストラクタは常に上記の宣言となります。 引数を受け取ることはできません。
これらはプログラム起動時に main() 関数よりも先に呼び出されるということだけが約束されています。 ただし、複数の静的コンストラクタがどのような順序で呼び出されるかという問題は定められていません。 他のクラスの静的コンストラクタによって初期化されるクラスメンバに、静的コンストラクタからアクセスするような場合、コンストラクタの実行順序に依存しないように記述しなければなりません。
import std.stream; class B { static this() { stdout.printf("B クラスの静的コンストラクタです\n"); } } class A { static this() { stdout.printf("A クラスの静的コンストラクタです\n"); } } int main() { stdout.printf("main 関数が実行されました\n"); return 0; }
B クラスの静的コンストラクタです A クラスの静的コンストラクタです main 関数が実行されました
このプログラムの A クラス及び B クラスは static 属性を持つ静的コンストラクタが定義されています。 実行結果を見れば、静的コンストラクタが main() 関数よりも先に呼び出されていることが分かります。
静的コンストラクタが正常に終了すれば、プログラムの終了時に静的デストラクタが呼び出されます。 静的デストラクタは、やはり static 属性を持つデストラクタのことです。
static ~this() { 本文 }
静的デストラクタは上記のように宣言されなければならず、引数を受けることはできません。 静的コンストラクタを持ち、エラーが発生せずに正常に終了できた場合にのみ、プログラム終了時に静的デストラクタが呼び出されます。
ファイルやネットワークポートの解放処理などが静的に行われなければならないというような限定されたケースで必要になるかもしれませんが、一般的なプログラムで静的デストラクタが必要になる設計は滅多にありません。
import std.stream; class B { static this() { stdout.printf("B クラスの静的コンストラクタです\n"); } static ~this() { stdout.printf("B クラスの静的デストラクタです\n"); } } class A { static this() { stdout.printf("A クラスの静的コンストラクタです\n"); } static ~this() { stdout.printf("A クラスの静的デストラクタです\n"); } } int main() { stdout.printf("main 関数が実行されました\n"); return 0; }
このプログラムを実行すれば、main() 関数終了後にそれぞれのクラスの静的デストラクタが呼び出されていることを確認できるでしょう。