あるインスタンスを、基本クラスのインスタンスとして扱うという仕組みはクラス・ライブラリの至る所で利用されています。Windowsアプリケーションでいえば、コントロールの親子関係が分かりやすい一例です。まずはこれについて見ていきます。
■Controlクラスのクラス階層
ボタンやテキスト・ボックスなどのコントロールの実体は、クラス・ライブラリでButtonクラスやTextBoxクラスにより定義されています。そしてこれらはすべてControlクラスの派生クラスとなっています。次の図3は、Controlクラスから継承しているいくつかのコントロールのクラス階層を図示したものです。
この図の一番下にあるように、WindowsフォームであるFormクラスは、Controlクラスの(間接的な)派生クラスです。ボタンやチェック・ボックス、コンボ・ボックスなどのコントロールも、Controlクラスから直接的に派生したクラスではありませんが、基本クラスのインスタンスはさらにその基本クラスのインスタンスとして扱うことができるので、この図にあるクラスのインスタンスは、すべてのContorolクラス型として参照できます。
ちなみに、このようなクラスの階層はリファレンス・マニュアルから知ることができます。Controlクラスを調べると次のような記述(図4左)があります。ここで「派生クラス」をクリックすると、Controlクラスを継承しているクラスが現れます(図4右)。
■コントロールの親子関係
ここで、次のようなデザインのWindowsフォームを考えてみましょう。フォームに2つのButtonコントロールと1つのGroupBoxコントロールをまず配置し、さらにGroupBoxコントロール上には2つのRadioButtonコントロールを配置します。この場合、2つのRadioButtonコントロールはGroupBoxコントロールによりグループ化されます。
このようにして配置したフォーム上のコントロールには、次の図6のような親子関係がVisual Studio .NETにより自動的に設定されます。2つのButtonコントロールとGroupBoxコントロールはフォームの子コントロールです。同様に、2つのRadioButtonコントロールはGroupBoxコントロールの子コントロールとなります。
ここでは詳しくは述べませんが、親子関係にあるコントロールは、親コントロールを移動させるとその子コントロールも移動する、子コントロールは親コントロール内にしか描画できない、子コントロールは親コントロールよりも常に手前(前面)になる、などの特徴があります。
■コントロールのコレクションであるControlsプロパティ
さて、このような親子関係を実現しているのは、Controlクラスで定義されているControlsプロパティです。このプロパティによりアクセスできるオブジェクト*1は、内部的に複数のコントロール(への参照)を保持することができます。このような複数のオブジェクトを保持できるオブジェクトは「コレクション・オブジェクト」と呼ばれます。
*1 実際には、このオブジェクトはControl.ControlCollectionクラスのオブジェクトです。これは、Controlクラスの内部で定義されたControlCollectionという名前のクラスで、このようなクラスは「入れ子クラス(Nested Class)」と呼ばれます。このクラスはControlクラスで利用されることがメインなので、入れ子クラスとして定義されています。
すべてのコントロールはControlクラスを継承しているため、すべてのコントロールがControlsプロパティを持っています。このため、次の図7のようにコントロールはほかのコントロールを子コントロールのコレクションとして保持することができます。
そしてこのControlsプロパティは「Add」というメソッドを持っており、このAddメソッドにより、コントロールをコレクションに追加することができます。Addメソッドのパラメータには、追加するコントロールを指定します。もはやいうまでもなく、Addメソッドのパラメータの型はControl型です。
次のコードは、上記の親子関係のあるコントロールをVisual Studio .NET(以降、VS.NET)を使ってフォーム上にデザインし、VS.NETで生成させたコードから、コントロールのインスタンス化とControlsプロパティへの設定の部分を抜き出したものです(C#のコード。VB.NETでは「this」の部分が「Me」になります)。
this.groupBox1 = new GroupBox();
this.button1 = new Button();
this.button2 = new Button();
this.radioButton1 = new RadioButton();
this.radioButton2 = new RadioButton();
this.groupBox1.Controls.Add(this.radioButton2);
this.groupBox1.Controls.Add(this.radioButton1);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.groupBox1);
ちなみに、「this」や「Me」はC#およびVB.NETのキーワードで、自分自身のインスタンスを参照するために使用するものです。上記のコードでは、thisがなくてもコンパイルは可能です。これについては次回で解説する予定です。
Copyright© Digital Advantage Corp. All Rights Reserved.