自動的にクラスの型を判別してCreateしてくれるような関数は出来ないでしょうか?
TTestAを渡すとTTestA.create、TTestBを渡すとTTestB.createというように、
渡す型に合わせてCreateする方法はないでしょうか。
type
TTestA=class(TObject) end;
TTestB=class(TObject) end;
function Creater(F:TObject):TObject;
begin
Result:= ? .create;
end;
var A:TTestA;
B:TTestB;
begin
A:=Creater(A); //TTestA型としてCreateされる
B:=Creater(B); //TTestB型としてCreateされる
end;
Creater関数の引数をTObjectのクラス参照型にすれば出来ると思います。
TObjectから派生したクラスは全てTObjectとして扱えますので。
但し、帰されるオブジェクトはTObject型になるので、下位のクラスで
実装したメンバを参照するには下位にキャストする必要がありますけど。
言語ガイドの仮想コンストラクタを参照してください。
解決できました。えびさんありがとうございます。
クラス参照型というのはこのような時に使うものなのですね。
キャスト自体もクラス参照型を使って出来たら便利なのですが、
それは無理でしょうか。
試してみればわかりますが、キャストはいりません。
そのためのクラス参照型です。
例えば、
type
TClassBaseClass=class of TClassBase;
TClassBase=class(TObject)
public
Data: String;
constructor Create(AOwner: TComponent); dynamic;// override;
end;
TClassA=class(TClassBase)
public
constructor Create(AOwner: TComponent); override;
end;
TClassB=class(TClassBase)
public
constructor Create(AOwner: TComponent); override;
end;
implementation
constructor TClassBase.Create(AOwner: TComponent);
begin
Data := 'unknown';
end;
constructor TClassA.Create(AOwner: TComponent);
begin
inherited;
Data := 'class is A';
end;
constructor TClassB.Create(AOwner: TComponent);
begin
inherited;
Data := 'class is B';
end;
-----------------------------
という定義だとして、
var
FactoryA: TClassBaseClass;
FactoryB: TClassBaseClass;
Obj: TClassBase;
begin
FactoryA := TClassA;
FactoryB := TClassB;
Obj := FactoryA.Create(Self);
ShowMessage(Obj.Data);
Obj.Free;
Obj := FactoryB.Create(Self);
ShowMessage(Obj.Data);
Obj.Free;
end;
という呼び出しをすれば、ClassAとClassBがちゃんと使い分けられていることが解ります。
FactoryAとFactoryBの違いは、代入したクラスの違いしかないです。
ツイート | ![]() |