Type foo DeclareProperty bar
(ByVal index AsInteger, ByVal value AsInteger) DeclareProperty bar(ByVal index AsInteger)AsInteger
dummy AsInteger EndType
Property foo.bar
(ByVal index AsInteger, ByVal value AsInteger) Print"Property set, index=" & index & ", value=" & value EndProperty
Property foo.bar(ByVal index AsInteger)AsInteger Print"Property get, index=" & index Property = 0 EndProperty
Type foo DeclareConstructor
(ByVal num_elements AsInteger) DeclareDestructor
() DeclareProperty bar
(ByVal index AsInteger, ByVal value AsInteger) DeclareProperty bar(ByVal index AsInteger)AsInteger Private:
x AsIntegerPtr
size AsInteger EndType
Constructor foo
(ByVal num_elements AsInteger)
x = CAllocate
(num_elements * SizeOf(Integer))
size = num_elements End Constructor
Destructor foo
() Deallocate(x) End Destructor
Property foo.bar
(ByVal index AsInteger, ByVal value AsInteger) If(index >= 0)And(index < size)Then
x[index] = value Else Error6 EndIf EndProperty
Property foo.bar(ByVal index AsInteger)AsInteger If(index >= 0)And(index < size)Then Property = x
[index] Else Error6 EndIf EndProperty
Dim baz As foo = foo
(10)
baz.bar(1) = 42 Print baz.bar
(1) Sleep
今回、私は、構築子と解体子を加えました。構築子と解体子は、動的メモリ配列 x を、割り当て、そして、割り当て解除します。素子数は、構築子で指定します。
次に、property の関数が呼び出されるとき、インデックスが配列の領域の中にあるかをチェックします。インデックスが配列の領域の中にあれば、要求された get または set を実行します。
指定されたインデックスが、区域外にあると、'Error 6' が発生します。 'Error 6' は、FB の 'out of bounds error' でプログラムを中止する方法です。あなたは、これを、あなた自身のエラー処理ルーチンに取り替えることができるのです。
このコードを、'baz.bar(1) = 42' から 'baz.bar(10) = 42' に変えて、試してみてください。私たちは、10 (index 0-9) の要素だけを指定したので、エラー処理の動作を見てください。
Type foo DeclareConstructor
(ByRef obj As foo)
... EndType
これは、私が現在説明しようとする理由に、非常に役立つものになります。
Deep/Shallow コピー
前の例で、コード 'Dim As foo b = a' を実行しました。これは、浅い(Shallow)コピーとして知られていることです。これは、単純に、データ項目全体に渡って、コピーします。しかし、これは望ましくない場合が、時々あります。メンバーの一つがポインタであることを、想像してください。この場合には、ポインタが示すアドレスが、そのままコピーされてしまいます。このため、両方のオブジェクトが、同じメモリを示すことになるのです。
下のコードは、この例です:
お分かりのように、コピー構築子は、'Dim As foo b = a' で呼ばれます。私たちは、今回、何らかのメモリを割り当てて、データを、新しいコピー構築子に、コピーします。それで、私たちは、ひとつのオブジェクトの x を、他に影響を及ぼさないで変更できるようになります。
私たちがメイン・コードを変えるなら、下のようになります。
Type foo DeclareConstructor
(ByVal num_elements AsInteger) DeclareConstructor
(ByRef obj As foo) DeclareDestructor
() DeclareOperatorLet
(ByRef obj As foo)
x AsIntegerPtr
size AsInteger EndType
Constructor foo
(ByVal num_elements AsInteger) Print"デフォルト構築子"
x = CAllocate
(SizeOf(Integer) * num_elements)
size = num_elements End Constructor
Constructor foo
(ByRef obj As foo) Print"コピー構築子"
x = CAllocate
(SizeOf(Integer) * obj.size)
size = obj.size For i AsInteger = 0To size - 1
x[i] = obj.x
[i] Next i End Constructor
Destructor foo
() Print"解体子" Deallocate(x) End Destructor
Operator foo.Let
(ByRef obj As foo) Print"代入"
x = Reallocate
(x, SizeOf(Integer) * obj.size)
size = obj.size For i AsInteger = 0To size - 1
x[i] = obj.x
[i] Next i EndOperator
Type bar DeclareConstructor
() DeclareConstructor
(ByRef obj As bar) DeclareConstructor
(ByVal n AsInteger) DeclareDestructor
() DeclareOperatorCast()AsAnyPtr DeclareOperatorLet
(ByVal n AsInteger) DeclareProperty foo
(ByVal n AsInteger) DeclareProperty foo()AsInteger
member AsAnyPtr EndType
Any ptr - void *
ZString ptr - char *
String - FBSTRING
byte - signed char
ubyte - bool
short - short
ushort - unsigned short
integer - int
uinteger - unsigned int
longint - long long
ulongint - unsigned long long