序論
多様性は、オブジェクト指向プログラムの強力なツールです。
多形メソッド(Sub か Function)は、オブジェクトの定義に応じて、動作が異なります。
たとえば、動物のオブジェクトには、犬には吠え声、猫には猫の鳴き声を発する、話し方があります。
FreeBASIC は以前は真の多型をサポートしていませんでした。
しかし、メソッド・ポインタを使うと、多相メソッドをシミュレートすることができます。
FreeBasic 0.90.0 以降 は、多様性を正式サポートしました。
多様性
多形のメソッドは、同じ型とパラメータ・リストを持つ、サブルーチンか関数です。しかし、異なるオブジェクトに縛られると、異なる振る舞いをします。
動物オブジェクトには、犬のための鳴き声と、猫のための鳴き声を発する、発声メソッドがあります。
FreeBasic には、まだクラスがないので、本当の多形のメソッドを実装することはできません。しかし、メソッド・ポインタを使って、振舞いをシミュレートできます。
下のリストは、一対の、定義と、拡張型の宣言を、示しています:
#define isdog 1
#define iscat 2
Type animal
Public:
speak As Sub
()
Declare Constructor
(anid As Integer)
End Type
#defines は、生成されるオブジェクトの型を伝えるために、Constructor に渡されます。
speak As Sub() 定義は、メソッド・ポインタを定義します。
見てお分かりでしょうが、2つの別のサブルーチンのアドレスは、発声方法ポインタに渡されます。
以下のリストは、異なる発声サブルーチンと、Constructor メソッドを示します:
'犬オブジェクトの、鳴き方
Sub Bark
()
Print "ワンワン!"
End Sub
'猫オブジェクトの鳴き方
Sub Meow
()
Print "ニャーオ!"
End Sub
'動物 ID に基づく、適切な鳴き方ポインタを設定します
Constructor animal
(anid As Integer)
If anid = isdog Then
This.speak = @Bark
ElseIf anid = iscat Then
This.speak = @Meow
End If
End Constructor
Bark サブルーチンは、オブジェクトが犬ならば呼ばれます。そして、Meow サブルーチンは、オブジェクトが猫ならば呼ばれます。
あなたは、メソッドをなぜ多重定義できないか、不思議に思うでしょう。
多重定義のメソッドに対して、型とパラメータ・リストはユニークでなければなりません。多形のメソッドでは、型とパラメータ・リストは、同じでなければなりません。
Bark と Meow は、同じパラメータ・リストを持っています。これは、パラメタではないので、メソッドを多重定義ることができません。
Constructor コードは、プログラムが、使うために呼ぶメソッドを決めるところです。
anid が isdog と等しいなら、発声メソッド・ポインタは、Bark サブルーチンのアドレスに設定されます。
anid が iscat と等しいなら、発声は、Meow サブルーチンのアドレスに設定されます。
addressof 演算子 @ は、Bark と Meow のアドレスを、発声ポインタに渡すため使われます。
this オブジェクト参照は、隠されたパラメタで、型に参照をつける Constructor に渡されます。この場合の型は、動物です。
あなたは、これを、型の中で内部変数を参照するために使用できます。
やるべく残っている唯一のことは、オブジェクトを作成して、初期化することです:
'犬と猫のオブジェクトを作成します
Dim myDog As animal = isdog
Dim mycat As animal = iscat
ここで、myDog と myCat は、適切なフラグが Constructor に渡されている状態で、作成されます。それで、適切な参照が、設定されます。
オブジェクトがいったん作成されると、あなたは、それぞれのオブジェクトの発声メソッドを呼ぶことができます。
'動物に鳴かせましょう
Print "犬が鳴きます:";
myDog.speak
()
Print "猫が鳴きます:";
myCat.speak
()
あなたは、同じ発生メソッドを呼んでいます、しかし、出力は異なっています:
犬が鳴きます:ワンワン!
猫が鳴きます:ニャーオ!
これは多形メソッドの本質です。
下は、これまで記述したことを合わせた、完全なプログラムです:
'メソッド・ポインタを使って、多様性をシミュレート
'Richard D. Clark (リチャード・D.クラーク)
'FreeBasic の CVS(Concurrent Versions System) バージョンを使います
'**********************************************
#define isdog 1
#define iscat 2
Type animal
Public:
speak As Sub
()
Declare Constructor
(anid As Integer)
End Type
'犬オブジェクトのための鳴き方
Sub Bark
()
Print "ワンワン!"
End Sub
'猫オブジェクトのための鳴き方
Sub Meow
()
Print "ニャーオ!"
End Sub
'動物 ID に基づく適切な鳴き方ポインタを設定します
Constructor animal
(anid As Integer)
If anid = isdog Then
This.speak = @Bark
ElseIf anid = iscat Then
This.speak = @Meow
End If
End Constructor
'犬と猫オブジェクトを作成します
Dim myDog As animal = isdog
Dim mycat As animal = iscat
'動物に鳴かせます
Print "犬が鳴きます:";
myDog.speak
()
Print "猫が鳴きます:";
myCat.speak
()
Sleep
End