クラス参照は、クラスを操作する時に使用されます。実際、あるクラスのインスタンス(オブジェクト)を生成する時には、このクラス参照を用いて作成されています。他にもクラスメソッドの呼び出しや、オブジェクトの型を調べる際にも利用されます。
あるクラスのオブジェクトを生成する際、コンストラクタを呼び出すことでそのオブジェクトが生成されることになります。この場合のコンストラクタ呼び出しの際にクラス参照を用いていることになります。
// クラス参照を用いてコンストラクタを呼び出す SomeObject := TSomeClass.Create;
クラス参照型は、実際に参照されるクラスの型がコンパイル時に分からないクラスなどに用いることができます。クラス参照型は、以下のようにして宣言されます。
TSomeClassRef = class of TSomeClass;
クラス参照型を用いた簡単な例を以下に示します。
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Button1: TButton; RadioGroup1: TRadioGroup; ListBox1: TListBox; procedure RadioGroup1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; TFruit = class(TObject) public procedure ShowFruit; virtual; abstract; end; TApple = class(TFruit) public procedure ShowFruit; override; end; TOrange = class(TFruit) public procedure ShowFruit; override; end; TBanana = class(TFruit) public procedure ShowFruit; override; end; TFruitClassRef = class of TFruit; // クラス参照型 var Form1: TForm1; implementation {$R *.dfm} var FruitClassRef: TFruitClassRef; { TApple } procedure TApple.ShowFruit; begin Form1.ListBox1.Items.Add('Apple !'); end; { TOrange } procedure TOrange.ShowFruit; begin Form1.ListBox1.Items.Add('Orange !'); end; { TBanana } procedure TBanana.ShowFruit; begin Form1.ListBox1.Items.Add('Banana !'); end; { TForm1 } procedure TForm1.RadioGroup1Click(Sender: TObject); begin case RadioGroup1.ItemIndex of 0: FruitClassRef := TApple; 1: FruitClassRef := TOrange; 2: FruitClassRef := TBanana; end; end; procedure TForm1.FormCreate(Sender: TObject); begin RadioGroup1.ItemIndex := 0; end; procedure TForm1.Button1Click(Sender: TObject); var SomeFruit: TFruit; begin SomeFruit := FruitClassRef.Create; SomeFruit.ShowFruit; SomeFruit.Free; end; end.
ボタンを押すと、RadioGroup で選択されているクラスがクラス参照型の変数に代入されて、そのクラスのオブジェクトが生成されている事になります。
SomeFruit := FruitClassRef.Create の部分は、コンパイル時には実際どのオブジェクトが生成されるか決定されていません。
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; RadioGroup1: TRadioGroup; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure RadioGroup1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} uses Unit2; var AbstractNameRef: TAbstractNameRef; procedure TForm1.Button1Click(Sender: TObject); var AbstractName: TAbstractName; begin AbstractName := AbstractNameRef.Create('Hello', 5); AbstractName.Show; AbstractName.Free; end; procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Clear; RadioGroup1.Items.Add('Decompose'); RadioGroup1.Items.Add('Repeat'); RadioGroup1.ItemIndex := 0; end; procedure TForm1.RadioGroup1Click(Sender: TObject); begin case RadioGroup1.ItemIndex of 0: AbstractNameRef := TDecomposeName; 1: AbstractNameRef := TRepeatName; end; end; end.
[ ファイル | 新規作成 | ユニット ] で新たにユニットを追加してください。
unit Unit2; interface type TAbstractName = class(TObject) private fName: string; fCount: Integer; public constructor Create(Name: string; Count: Integer); function Process: string; virtual; abstract; procedure Show; property Name: string read fName; property Count: Integer read fCount; end; TDecomposeName = class(TAbstractName) public function Process: string; override; end; TRepeatName = class(TAbstractName) public function Process: string; override; end; TAbstractNameRef = class of TAbstractName; implementation uses Unit1; { TAbstractName } constructor TAbstractName.Create(Name: string; Count: Integer); begin fName := Name; fCount := Count; end; procedure TAbstractName.Show; begin Form1.Memo1.Lines.Add(Process); end; { TDecomposeName } function TDecomposeName.Process: string; var i, j: Integer; begin Result := ''; for i := 0 to Length(Name)-1 do begin for j := 0 to Count-1 do Result := Result + Name[i+1]; Result := Result + #13#10; end; end; { TRepeatName } function TRepeatName.Process: string; var i: Integer; begin Result := ''; for i := 0 to Count-1 do Result := Result+Name+#13#10; end; end.