オブジェクト指向のツボ 〜Vol6. コンポジション〜

オブジェクト指向でプログラミングをすると、あるクラスを他のクラスから再利用する場面によく出くわします。継承とコンポジションは、双方ともクラス同士の関係性を築くものですが、意味は異なります。継承の関係を持たせるか、あるいはコンポジションの関係を持たせるかは、プログラマー次第ではありますが、その違いははっきりと認識しておかなければなりません。

ここで、あるクラスが他のクラスの"一種である(is a kind of)" ときは継承を、"持っている(has)" ときはコンポジションの関係を持たせればよいということになります。例えば、シャツとボタンの関係は、コンポジション(シャツはボタンを持ち合わせる)ということになりますが、シャツとTシャツはそのような関係にはなりません。このようなとき、Tシャツはシャツの一種であるという認識が必要です。

あらためて、「全体-部分」クラス同士がこのような関係を持つことを、コンポジション(集約)といいます。実はこの考え方、普段の私たちの身の回りでは、ごくごく当たり前のように、使用されているのです。

例えば、皆さんが今使っているパソコンが良い例です。ディスプレイ、キーボード、マウスなどは、パソコンの部品、即ち、パソコンとコンポジションの関係にあるといえます。このように、あるクラスとその中で部品化されたクラスというのがコンポジションということになります。

コンポジションのやり方

「構造体のメンバ変数に構造体を指定する」これをクラスに当てはめて考えると、コンポジションの関係を持たせることができます。ようは、あるクラスのメンバ変数として他のクラスを指定しまえばいいわけです。

'部品となるクラスを定義
Class CParts
    ...
End Class

'親クラスを定義
Class CParent
    objParts1 As CParts
    objParts2 As CParts
    ...
End Class

コンストラクタ/デストラクタの呼び出し順序

コンポジションの関係を持つ部品側のクラスも、当然のように初期化&終了処理が呼び出されることになります。通常であれば、暗黙的に下のような順序でコンストラクタ/デストラクタが呼び出されます。

部品クラスのコンストラクタ

親クラスのコンストラクタ

処理...

親クラスのデストラクタ

部品クラスのデストラクタ

コンストラクタとは全くの逆順序でデストラクタが呼ばれるのは、注目したいところですね。これは継承の際も同様のことが言えます。

ここで注意点が1つ。親クラスを生成したときに暗黙的に呼び出される部品クラスのコンストラクタは、引数を持たないものだけになります。引数有りコンストラクタを有する部品クラスが存在するときは、親クラスのコンストラクタ内で任意にその部品クラスのコンストラクタを呼び出してやる必要があります。

下の例では、引数有りコンストラクタを明示的に呼び出しています。

#N88BASIC

Class CParts1
Public
    Sub CParts1()
        Print "CParts1のコンストラクタ(引数を持たない)。"
    End Sub
    Sub ~CParts1()
        Print "CParts1のデストラクタ。"
    End Sub
End Class

Class CParts2
Public
    Sub CParts2(a As Long)
        Print "CParts2のコンストラクタ(引数を持つ)。引数の値は、";a
    End Sub
    Sub ~CParts2()
        Print "CParts2のデストラクタ。"
    End Sub
End Class

Class CParent
    obj1 As CParts1
    obj2 As CParts2
Public
    Sub CParent()

        '引数有りコンストラクタは明示的に呼び出す
        obj2.CParts2(10)

        Print "親クラスのコンストラクタ"
    End Sub
    Sub ~CParent()
        Print "親クラスのデストラクタ"
    End Sub
End Class

Dim obj As CParent

↑実行結果



講座インデックスへ戻る ©2005 Discoversoft