Dではstruct
で複合型もしくはカスタム型を定義できます:
struct Person {
int age;
int height;
float ageXHeight;
}
struct
は(new
で作成されない限り)常にスタックに構築され、
代入や関数呼び出しの引数では値としてコピーされます。
auto p = Person(30, 180, 3.1415);
auto t = p; // コピー
struct
型のオブジェクトが新規に作成されるとき、
そのメンバはstruct
内で定義された順に初期化されます。
カスタムコンストラクタはthis(...)
メンバ関数で定義できます。
名前の衝突を回避したいときは、this
を使って現在のインスタンスに明示的にアクセスできます:
struct Person {
this(int age, int height) {
this.age = age;
this.height = height;
this.ageXHeight = cast(float)age * height;
}
...
Person p = Person(30, 180); // 初期化
p = Person(30, 180); // 新しいインスタンスへ代入
struct
は複数のメンバ関数を持つことができます。
メンバ関数はデフォルトでpublic
で、外部からアクセスが可能です。
これはprivate
にすることも可能で、その場合同じstruct
のメンバ関数か、
同じモジュール内のコードからのみ呼び出せるようになります。
struct Person {
void doStuff() {
...
private void privateStuff() {
...
p.doStuff(); // メソッド doStuff を呼び出す
p.privateStuff(); // これは禁止されています
メンバ関数がconst
で宣言されている場合、そのメンバを変更することはできません。
これはコンパイラにより強制されます。
メンバ関数をconst
にすると、const
またはimmutable
オブジェクトから呼び出せるようになり、
さらにこの関数がオブジェクトの状態を変更しないことが呼び出し元に保証されます。
メンバ関数がstatic
で宣言されると、
その関数はインスタンス化されたオブジェクトなしに呼び出せるようになります
(例: Person.myStatic()
)が、非static
メンバにアクセスできなくなります。
これはメソッドがオブジェクトメンバフィールドにアクセスする必要はないが、
論理的には同じクラスに属するときに使えます。
明示的インスタンスを作ることなく機能を提供するのにも使えます。
例えばシングルトンデザインパターンの実装にはstatic
が使われることがあります。
struct
は他のstruct
から継承できないことに注意してください。
型ヒエラルキーは、後のセクションで見ていくクラスを用いてのみ構築可能です。
しかし、alias this
やmixin
で簡単にポリモーフィックな継承が可能です。
struct Vector3
に以下の関数を実装し、サンプルアプリケーションを正常に実行されるようにしましょう:
length()
- ベクトルの長さを返す
dot(Vector3)
- 2つのベクトルのドット積を返す
toString()
- ベクトルの文字列表現を返す
関数 std.string.format
はformat("MyInt = %d", myInt)
のようなprintf
風の構文を使って文字列を返します。
文字列は後のセクションで詳しく解説します。