さまざまなキーワード
Type (UDT),
Type (Alias),
Type (Temporary),
Union
定義
Type と
Union という異なるキーワードが、ユーザーの頭の中で混同されている可能性があります(ドキュメントのいくつかのページで、それぞれを互いに区別していますが):
- Type (UDT):
重複しないデータのユーザー構造を宣言/定義し、メンバー手続きになりえます:
- 名前付き型: データ型を宣言するために参照できる名前を持つ型。
- 匿名の型: 名前がないため、名前で参照できない型。
- Type(Alias):
他のユーザー定義データ型または標準データ型から、ユーザー定義型名を宣言します。
- Type (Temporary):
- Union:
メンバー手続きと重複するデータのユーザー構造を宣言/定義しますが、コンストラクターまたはデストラクタを持つオブジェクトフィールド(またはベース)は(間接的に直接)定義しません:
- 名前付き共用体: データ型を宣言するために参照できる名前を持つ共用体。
- 匿名の共用体: 名前がないため、名前で参照できない共用体。
型/共用体構造の複雑さのレベル:
- 自明な構造: メンバー手続きを持たない、名前付きまたは匿名の構造(間接的に直接)。
- 複雑な構造体: メンバー 手続きを持つ名前付き構造体 (直接的または間接的)。
- 拡張構造: 別の名前付き構造体から継承する名前付き構造体。
型/共用体構造は、別の型/共用体構造内にネストすることもできます:
- 入れ子になった名前付き型: 別の名前付き型/共用体構造内に入れ子になっている名前付き型。
- 入れ子になった匿名型: 別の名前付きまたは匿名共用体構造内に入れ子になっている匿名型。
- 入れ子になった名前付き共用体: 別の名前付き型/共用体構造内に入れ子になっている名前付き共用体。
- 入れ子になった匿名共用体: 別の名前付きまたは匿名型構造内にネストされた匿名共用体。
型 (エイリアス) 宣言は、型/共用体構造内に入れ子にすることもできます。
- 入れ子にされた型(エイリアス)宣言では、型/共用体内で、場所のアクセス権に従って内部エイリアスを宣言できます。
記述
ネストされた名前付き型/共用体の主な目的は次のとおりです:
- 型と共用体の間の関係を理解可能な方法で表現できるようにするため。
- このような型やユニオンは、独自の名前空間を持ち、その中で関連するシンボルを整理し、型に対してのみ可視性アクセス(
Public/
Protected/
Private)を提供し、メンバーへのアクセスをよりきめ細かく制御できるようにします。
- 型/共用体の間に循環依存関係がある場合、入れ子になった名前付き型/共用体を使用することで、Type(Alias)の使用や前方参照を避けることができます。
ネストされた名前付き型/共用体がない場合:
- Type/Union 間で関係を表現することは可能ですが、すべての Type/Union がパブリックにアクセス可能でなければならないというデメリットがあります。
- Namespace の使用は、可視性の範囲を整理するのに役立ちますが、問題は、*すべての*型/ユニオンが可視でなければならないことに変わりはありません。
- このため、ユーザー(または作成者自身)が意図しない方法で Type/Union を使用してしまい、有効ではあるがエラーを起こしやすいコードを作成する可能性があります。
- この問題は、Type/Union を前方宣言で非表示にしたり(Type (Alias))、プライベート・シンボルを別のモジュールに入れることで軽減できますが、コードが断片化することで新たな問題が発生します。
匿名型 (または共用体):
- 名前がなく、名前で参照できません。
- Named Union (または Type) または別の Anonymous Union (または Type) 内にだけネストされて表示される場合があります。
- ネストした構造体内のフィールドを、別々のメモリ位置(Nested Type)または重複するメモリ位置(Nested Union)に宣言します。
- フィールドを参照できます。
- 静的メンバーや手続き宣言を (直接的にも間接的にも) 含めることはできません => 自明な構造。
名前付き型 (または共用体):
- フィールド、変数、パラメーター、配列などのデータ型を宣言するために参照できる名前があります。
- 単独で、または他の名前付き型(またはUnion)の中にネストして表示することができます。
- Type (または Union) の宣言のみ。
- ネストする構造内でフィールドを宣言しないため、サイズが追加されません。
- 静的メンバーまたは手続き宣言を (直接的または間接的に) 含めることができます => 自明/複雑な構造。
Type/Union 構造と(対)スコープの場所の、複雑さのレベル:
- 自明な構造: グローバル/名前空間/ネストされたスコープ、またはローカル スコープ内 (Scope や Sub など) で宣言できる、名前付きまたは匿名型/共用体。
- 複雑な構造: グローバル/ネームスペース/ネストされたスコープで宣言し、グローバル/ネームスペース スコープで定義する必要がある、名前付きタイプ/ユニオン。
- 拡張構造: Base のスコープ (現在は Base と同じスコープ) に対する可視性を持つスコープで宣言された名前付き Type/Union。
メイン構造 (Type/Union) は常に名前付きでなければならず、他の (ネストされた) 構造は匿名または名前付きにすることができます。
名前付き型/共用体で実行できるほとんどすべてのことは、継承機能 (ベースまたは派生として) を含め、ネストされた名前付き型/共用体でも実行できます。
ネストされた匿名型/共用体は、手続き メンバーまたは静的データ メンバーを持つことはできません (ローカル スコープ内の名前付き型/共用体と同じ制限)。
例
例: 'Named Type' <- 'Nested Anonymous Union' <- 'Nested Anonymous Type':
Type T '' named
Union '' anonymous
Dim a As Short
Type '' anonymous
Dim b1 As Byte
Dim b2 As Byte
End Type
End Union
Declare Sub proc()
End Type
Sub T.proc()
b1 = 1
b2 = 2
Print b1, b2, a
End Sub
Dim x As T
x.proc()
Sleep
ネストされた名前付き型を使って、2 つの主要な型間の循環的な依存関係を解決する例 (型エイリアスの使用と前方参照を避けるため):
'' example of two dependent types, with a type alias and a forward referencing:
'
'Type list As list_
'
'Type listnode
' text As String
' parent As list Ptr
'End Type
'
'Type list_
' first As listnode Ptr
' count As Integer
'End Type
'' same example of two dependent types, but with simply one of them a Nested Named Type:
Type list
count As Integer
Type listnode
text As String
parent As list Ptr
End Type
first As listnode Ptr
End Type
アクセス構文とアクセス権を確認する例:
Type UDT1
Private:
Dim As Integer I1 = 123
Type UDT2
Private:
Dim As Integer I2 = 456
Public:
Declare Function returnI2() As Integer
End Type
Public:
Type UDT3
Private:
Dim As Integer I3 = 789
Public:
Declare Function returnI3() As Integer
End Type
Declare Function returnI1() As Integer
Dim As UDT2 t2
Dim As UDT3 t3
End Type
Function UDT1.returnI1() As Integer
Return This.I1
End Function
Function UDT1.UDT2.returnI2() As Integer
Return This.I2
End Function
Function UDT1.UDT3.returnI3() As Integer
Return This.I3
End Function
Dim As UDT1 t11
'Print t11.I1 '' error 202: Illegal member access
'' I1 is in the private section of UDT1
Print t11.returnI1() '' OK, returnI1() is in the public section of UDT1
'Print t11.t2.I2 '' error 202: Illegal member access
'' t2 is in the public section of UDT1, but I2 is in the private section of UDT2
Print t11.t2.returnI2() '' OK, t2 is in the public section of UDT1, and returnI2() is in the public section of UDT2
'Print t11.t3.I3 '' error 202: Illegal member access
'' t3 is in the public section of UDT1, but I3 is in the private section of UDT3
Print t11.t3.returnI3() '' OK, t3 is in the public section of UDT1, and returnI3() is in the public section of UDT3
Print
'Dim As UDT1.UDT2 t21 '' error 202: Illegal member access
'' UDT2 is in the private section of UDT1
Dim As UDT1.UDT3 t31 '' OK, UDT3 is in the public section of UDT1
'Print t31.I3 '' error 202: Illegal member access
'' I3 is in the private section of UDT3
Print t31.returnI3() '' OK, returnI3() is in the public section of UDT3
Sleep
ネストされた名前付き型でできることの例
これは宣言の部分だけですが、指摘に値するいくつかの点をあげています:
Type MemoryTable
Private:
'' プライベート メンバーは MemoryTable 内でのみ可視
Const default_alignment = 16
m_bytes_per_node As UInteger = 0
m_nodes_per_chunk As UInteger = 0
Type Chunk
m_owner As MemoryTable Ptr
m_nodes As UInteger
m_prevChunk As Chunk Ptr
m_data As Any Ptr
End Type
Declare Sub allocChunk()
m_headChunk As Chunk Ptr = 0
Protected:
'' 保護されたメンバーは MemoryTable および派生型内で可視
Declare Constructor()
Type Iterator
Private:
m_chunk As Chunk Ptr
m_index As Integer
Protected:
Declare Constructor()
Declare Constructor(ByVal table As MemoryTable Ptr)
Declare Property item() As Any Ptr
Public:
Declare Property hasItem() As Boolean
Declare Sub nextItem()
End Type
Declare Function newNode() As Any Ptr
Public:
'' 型の外部から見える public メンバー
Declare Constructor(ByVal bytes As UInteger, nodes As UInteger)
Declare Destructor()
End Type
参照