クラス参照は、クラスを操作する時に使用されます。実際、あるクラスのインスタンス(オブジェクト)を生成する時には、このクラス参照を用いて作成されています。他にもクラスメソッドの呼び出しや、オブジェクトの型を調べる際にも利用されます。
あるクラスのオブジェクトを生成する際、コンストラクタを呼び出すことでそのオブジェクトが生成されることになります。この場合のコンストラクタ呼び出しの際にクラス参照を用いていることになります。
// クラス参照を用いてコンストラクタを呼び出す
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.