ユーザー定義型
- ユーザー定義型
- 概要
- 型公開修飾子 - public private(class,interface,pod,struct)
- メンバ公開修飾子 - public private(class,struct)
- オーバーライドチェック - override(class)
- 不変条件 - invariant(class,pod,struct)
- 委譲 - implement(class)
- 委譲 (class)
- コンストラクタ - this() (class,pod,struct)
- デストラクタ - ~this() (class,struct)
- 静的コンストラクタ・デストラクタ - static this(), static ~this() (class,struct,pod)
- 静的コンストラクタ - static this() (class,struct,pod,utility)
- メンバ関数/変数 (class,interface,struct,pod)
- 静的デストラクタ - static ~this() (class,struct,pod,utility)
- 静的メンバ関数 (class,interface,pod,struct,utility)
- 静的メンバ変数 (class,pod,struct)
- メンバ関数 (class,interface,struct,pod)
- メンバ変数 (class,struct,pod)
概要
項目 | pod | struct | class | interface | utility |
デフォルトコンストラクタのユーザー定義 | x *1 | x *1 | o | x | x |
コンストラクタ | o | o | o | x | x | デストラクタ | x | o | o | x | x | 静的コンストラクタ 静的デストラクタ | o | o | o | x | o |
structメンバ変数 | x | o | o | x | x | objectメンバ変数 | x | o | o | x | x | メンバ関数 | o | o | o | o | x |
ガベージコレクタ対象 | x | x | o | o | x | インターフェースの継承 | x | x | o | o | x | 公開修飾子(public/private) | o | o | o | x | o | 代入オーバーロード | x | o | x | x | x | invariant | o | o | o | x | x |
1 : 全部0で初期化
*1 : 全部0(規定値)で初期化。
structでも許さない理由は,static変数にstructな変数を定義すると,初期化時に関数コールが走ってしまうため。
関数コールは.init初期化が終わった後から呼び出すように統一したい。
interface
- C#,Dのinterfaceと同じ
- interfaceは複数にinterfaceを継承することができる
- 純粋仮装関数にはabstractキーワードを先頭につける
- <要検討>デフォルト実装を書くことを許す(本当は許さない方が厳密なinterfaceなんですけど)
1
2
3
4
5
6
7
|
-
|
|
|
|
!
| interface IButtonListener
{
abstract void onButtonPush( in IButton sender )const;
void onButtonFocused( in IButton sender )const{}
};
|
class
- 強制的にobject型を継承している
- 他の言語でよくあるclassの継承は不可
- 他の言語でよくあるclassの継承は不可 -> C#のような1つだけ継承できるのはしてもいいんじゃないかと思い始めてる最近
- interfaceは何個でも継承できる
pod
- plain object data
- C言語のstructに近い
- デフォルトコンストラクタはオブジェクトのメモリ領域を0で初期化する扱いになる
struct
- 継承のないC++のクラス・D言語のscope classと同じ
- ガベージコレクト対象ではないので参照を保持することができない
型公開修飾子 - public private(class,interface,pod,struct)
- デフォルトはpublic
- 名前空間直下のprivateな型は同じソース内からしかアクセスができない
- ガベージコレクト対象ではないので,structなオブジェクトインスタンスの参照(オブジェクトハンドル)を保持することができない
utility
- static関数のみ提供する型,インスタンスを作ることができない。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
-
|
|
!
-
|
|
|
|
|
|
|
!
| #spanend
#spandel
module Mod.B;
#spanend
#spandel
#spanend
#spandel
private pod A
#spanend
#spandel
{
#spanend
#spandel
};
#spanend
#spandel
#spanend
#spandel
#spanend
#spandel
pod B #spanend
#spandel
{
#spanend
A a;
#spandel
#spanend
pod C { int x; }
#spandel
};
#spanend
#spandel
#spanend
#spandel
|
メンバ公開修飾子 - public private(class,struct)
- public/privateのみ。protectedは無い。
- protectedは無い。
- デフォルトはpublic
- コロンを使うC++スタイル、メンバ変数・関数に直接記述するJAVAスタイルの両方に対応
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
|
|
|
|
|
|
|
|
|
|
|
!
| class A
{
public:
void funcPubA(){} private:
void funcPriA(){}
public void funcPubB(){} private void funcPriB(){}
};
|
オーバーライドチェック - override(class)
不変条件 - invariant(class,pod,struct)
- (all)Dのinvariantと同じ
- (all)Dのinvariantとほぼ同じ
- 呼び出されるタイミング
- publicなメンバ関数の実行直前・直後
- ↑ publicメンバ変数によって自動で作成される関数も対象に含む。(メンバ変数の項を参照)
- コンストラクタの直後
- デストラクタの直前
- invariant関数内でpure constメンバ関数以外のメンバ関数を呼び出すことを禁止。
- <要検討>structで再帰呼び出しされたらどうしよう(classはカウンタ持たせればいいかな)
委譲 - implement(class)
- interfaceのデフォルト実装を別オブジェクトに委譲するキーワード
委譲 (class)
- interfaceのデフォルト実装を別オブジェクトに委譲する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
-
|
|
!
-
|
|
!
-
|
|
|
|
|
|
|
!
-
|
|
|
|
|
!
| interface IButtonListener
{
abstract void onPushed();
void onFocused(){}
};
class Hoge : IButtonListener
{
public:
override void onPushed(){}
};
#spandel
class A : IButtonListener implement mHoge
#spanend
#spanadd
class A : IButtonListener = mHoge
#spanend
{
private:
Hoge mHoge = new Hoge();
Hoge@ mHoge;
};
#spandel
class B : public IButtonListener implement mHoge
#spanend
#spanadd
class B : public IButtonListener = mHoge
#spanend
{
override void onFocused() { }
private:
Hoge mHoge = new Hoge();
Hoge@ mHoge;
};
|
コンストラクタ - this() (class,pod,struct)
- (all)D言語の形式を採用し、関数名はthisを使う
- (all)別コンストラクタ関数コールは可能
- (all)どのコンストラクタよりも前に.Initデータをメモリ領域にセットされる(D言語と同じふるまいをする)
- (pod)デフォルトコンストラクタは定義できない(0初期化固定)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
-
|
|
-
|
!
|
|
-
|
|
|
!
|
|
|
|
|
!
| class A
{
public:
this()
{
mY = mX + 1;
}
this(in int x, in int y)
: this()
{
this();
mX = x;
mY = y;
}
int x = 1;
int y;
int mX = 1;
int mY;
};
|
デストラクタ - ~this() (class,struct)
0
1
2
3
4
5
| class A
{
public:
~this()
{
}
};
|
静的コンストラクタ・デストラクタ - static this(), static ~this() (class,struct,pod)
静的コンストラクタ - static this() (class,struct,pod,utility)
- D言語と同じ
- 静的コンストラクタが呼ばれる前に,.initデータがメモリ領域にコピーされる。
メンバ関数/変数 (class,interface,struct,pod)
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #spanend
#spanadd
class A
#spanend
#spanadd
{
#spanend
static int hoge = 1;
static int foo; // hoge * 2を代入したいが,他の変数を参照することができない
static this()
{
// この時点で,.initデータがコピー済み。
// つまり,hogeには1,fooには0(デフォルト値)が代入済み
#spanadd
#spanend
foo = hoge * 2; // ここなら他の変数を参照することができる。
}
#spanadd
};
#spanend
#spanadd
|
静的デストラクタ - static ~this() (class,struct,pod,utility)
0
1
2
3
4
5
6
7
8
9
10
11
12
| #spanend
#spanadd
class A
#spanend
#spanadd
{
#spanend
static ~this()
{
}
#spanadd
};
#spanend
#spanadd
|
静的メンバ関数 (class,interface,pod,struct,utility)
静的メンバ変数 (class,pod,struct)
メンバ関数 (class,interface,struct,pod)
- (all)C++でいうメンバ関数のconst修飾子はあり。引数リストの括弧の後ろにconstを付ける。
- (all)staticメンバ関数が使える。
- (class,pod,struct)staticメンバ変数が使える。仕様はD言語と同じ。
- (class,struct)公開修飾子をつけられる
- (class)抽象関数にoverrideキーワードが使える
- (interface)メンバ変数は使えない
- (interface)純粋仮装関数には先頭にabstractキーワードを付ける
- (interface)デフォルト実装はstatic関数として同じ名前の関数が定義される。
1
2
3
4
5
6
7
8
|
-
|
|
|
|
|
!
| interface IName
{
string getName(){ return "NoName"; }
};
|
メンバ変数 (class,struct,pod)
- publicなメンバ変数は関数に展開される。
- こうすることで変数のオフセット情報を知る必要がなくなり,再コンパイルの回数を減らすことができる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
|
!
| #spanend
#spanadd
struct Hoge
#spanend
#spanadd
{
#spanend
public int a;
#spanadd
#spanend
static void test()
{
Hoge h;
h.a = 3;
#spanadd
#spanend
h.a = Hoge().a + Hoge().a;
#spanadd
#spanend
h.a += 3;
}
#spanadd
}
#spanend
#spanadd
|
inlineメンバ変数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
-
|
|
|
|
|
|
!
| #spanend
#spanadd
class Hoge
#spanend
#spanadd
{
#spanend
public inline Foo@ a;
#spanadd
};
#spanend
#spanadd
#spanend
#spanadd
#spanend
#spanadd
|
|