クラス参照とクラス参照型

クラス参照は、クラスを操作する時に使用されます。実際、あるクラスのインスタンス(オブジェクト)を生成する時には、このクラス参照を用いて作成されています。他にもクラスメソッドの呼び出しや、オブジェクトの型を調べる際にも利用されます。

あるクラスのオブジェクトを生成する際、コンストラクタを呼び出すことでそのオブジェクトが生成されることになります。この場合のコンストラクタ呼び出しの際にクラス参照を用いていることになります。

// クラス参照を用いてコンストラクタを呼び出す
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.


up next
Last update: 2002/11/29