从 类 数组创建实例
Create instances from array of classes
我的 class 定义是:
TAnimal = class(TInterfacedObject)
public
constructor Create; overload;
constructor Create(param : string); overload;
end;
IAnimal = interface
procedure DoSomething;
end;
TDog = class(TAnimal, IAnimal)
public
procedure DoSomething;
end;
TCat = class(TAnimal, IAnimal)
public
procedure DoSomething;
end;
示例代码:
procedure TForm1.DogButtonPressed(Sender: TObject);
var
myDog : TDog;
I : Integer;
begin
myDog := TDog.Create('123');
I := Length(myQueue);
SetLength(myQueue, I+1);
myQueue[I] := TDog; //Probably not the way to do it...??
end;
procedure TForm1.CatButtonPressed(Sender: TObject);
var
myCat : TCat;
I : Integer;
begin
myCat := TCat.Create('123');
I := Length(myQueue);
SetLength(myQueue, I+1);
myQueue[I] := TCat; //Probably not the way to do it...??
end;
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
MyInterface : IAnimal; //Interface variable
I : Integer;
begin
for I := Low(myQueue) to High(myQueue) do
begin
MyInterface := myQueue[I].Create('123'); //Create instance of relevant class
MyInterface.DoSomething;
end;
end;
那么,假设您有一个包含三个按钮的表单。一个 "Dog" 按钮,一个 "Cat" 按钮和一个 "Process Queue" 按钮。当您按下 "Dog" 按钮或 "Cat" 按钮时,相关的 class 将添加到数组中以充当队列。当您随后按下 "Process Queue" 按钮时,程序将逐步遍历数组,创建相关 class 的对象,然后调用在该 class 中实现的接口方法。请牢记我上面的示例代码,如何实现?
简单的方法显然是将 class 名称作为字符串添加到字符串数组,然后在 OnProcessQueueButtonPressed
过程中使用 if
语句,例如:
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
MyInterface : IAnimal; //Interface variable
I : Integer;
begin
for I := Low(myQueue) to High(myQueue) do
begin
if myQueue[I] = 'TDog' then
MyInterface := TDog.Create('123');
if myQueue[I] = 'TCat' then
MyInterface := TCat.Create('123');
MyInterface.DoSomething;
end;
end;
我试图避免这种情况,因为每次我添加一个新的 class 我都必须记住为新的 class.[=17 添加一个 if
块=]
您可以使用 class reference 来做到这一点。像这样定义你的 class 引用类型:
type
TAnimalClass = class of TAnimal;
并安排TAnimal
支持接口:
type
IAnimal = interface
procedure DoSomething;
end;
TAnimal = class(TInterfacedObject, IAnimal)
public
constructor Create; overload;
constructor Create(param: string); overload;
procedure DoSomething; virtual; abstract;
end;
TDog = class(TAnimal)
public
procedure DoSomething; override;
end;
TCat = class(TAnimal)
public
procedure DoSomething; override;
end;
您对数组的使用导致代码相当混乱。更好的方法是使用列表对象。
var
myQueue: TList<TAnimalClass>;
现在你可以这样写代码了:
procedure TForm1.DogButtonPressed(Sender: TObject);
begin
myQueue.Add(TDog);
end;
procedure TForm1.CatButtonPressed(Sender: TObject);
begin
myQueue.Add(TCat);
end;
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
AnimalClass: TAnimalClass;
Animal: IAnimal;
begin
for AnimalClass in myQueue do
begin
Animal := AnimalClass.Create('123');
Animal.DoSomething;
end;
myQueue.Clear;
end;
您需要在适当的时候创建和销毁 myQueue
的实例。我假设您已经知道该怎么做。
使用 class 引用时的一个细微差别是您通常在基 class 中提供一个虚拟构造函数。那是因为当你使用 class 引用创建实例时,你调用了基 class 中声明的构造函数。如果该构造函数不是虚拟的,那么您派生的 class 构造函数代码将不会被执行。
当然,以这种方式使用 class 引用会使界面变得毫无意义。
我的 class 定义是:
TAnimal = class(TInterfacedObject)
public
constructor Create; overload;
constructor Create(param : string); overload;
end;
IAnimal = interface
procedure DoSomething;
end;
TDog = class(TAnimal, IAnimal)
public
procedure DoSomething;
end;
TCat = class(TAnimal, IAnimal)
public
procedure DoSomething;
end;
示例代码:
procedure TForm1.DogButtonPressed(Sender: TObject);
var
myDog : TDog;
I : Integer;
begin
myDog := TDog.Create('123');
I := Length(myQueue);
SetLength(myQueue, I+1);
myQueue[I] := TDog; //Probably not the way to do it...??
end;
procedure TForm1.CatButtonPressed(Sender: TObject);
var
myCat : TCat;
I : Integer;
begin
myCat := TCat.Create('123');
I := Length(myQueue);
SetLength(myQueue, I+1);
myQueue[I] := TCat; //Probably not the way to do it...??
end;
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
MyInterface : IAnimal; //Interface variable
I : Integer;
begin
for I := Low(myQueue) to High(myQueue) do
begin
MyInterface := myQueue[I].Create('123'); //Create instance of relevant class
MyInterface.DoSomething;
end;
end;
那么,假设您有一个包含三个按钮的表单。一个 "Dog" 按钮,一个 "Cat" 按钮和一个 "Process Queue" 按钮。当您按下 "Dog" 按钮或 "Cat" 按钮时,相关的 class 将添加到数组中以充当队列。当您随后按下 "Process Queue" 按钮时,程序将逐步遍历数组,创建相关 class 的对象,然后调用在该 class 中实现的接口方法。请牢记我上面的示例代码,如何实现?
简单的方法显然是将 class 名称作为字符串添加到字符串数组,然后在 OnProcessQueueButtonPressed
过程中使用 if
语句,例如:
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
MyInterface : IAnimal; //Interface variable
I : Integer;
begin
for I := Low(myQueue) to High(myQueue) do
begin
if myQueue[I] = 'TDog' then
MyInterface := TDog.Create('123');
if myQueue[I] = 'TCat' then
MyInterface := TCat.Create('123');
MyInterface.DoSomething;
end;
end;
我试图避免这种情况,因为每次我添加一个新的 class 我都必须记住为新的 class.[=17 添加一个 if
块=]
您可以使用 class reference 来做到这一点。像这样定义你的 class 引用类型:
type
TAnimalClass = class of TAnimal;
并安排TAnimal
支持接口:
type
IAnimal = interface
procedure DoSomething;
end;
TAnimal = class(TInterfacedObject, IAnimal)
public
constructor Create; overload;
constructor Create(param: string); overload;
procedure DoSomething; virtual; abstract;
end;
TDog = class(TAnimal)
public
procedure DoSomething; override;
end;
TCat = class(TAnimal)
public
procedure DoSomething; override;
end;
您对数组的使用导致代码相当混乱。更好的方法是使用列表对象。
var
myQueue: TList<TAnimalClass>;
现在你可以这样写代码了:
procedure TForm1.DogButtonPressed(Sender: TObject);
begin
myQueue.Add(TDog);
end;
procedure TForm1.CatButtonPressed(Sender: TObject);
begin
myQueue.Add(TCat);
end;
procedure TForm1.OnProcessQueueButtonPressed(Sender: TObject);
var
AnimalClass: TAnimalClass;
Animal: IAnimal;
begin
for AnimalClass in myQueue do
begin
Animal := AnimalClass.Create('123');
Animal.DoSomething;
end;
myQueue.Clear;
end;
您需要在适当的时候创建和销毁 myQueue
的实例。我假设您已经知道该怎么做。
使用 class 引用时的一个细微差别是您通常在基 class 中提供一个虚拟构造函数。那是因为当你使用 class 引用创建实例时,你调用了基 class 中声明的构造函数。如果该构造函数不是虚拟的,那么您派生的 class 构造函数代码将不会被执行。
当然,以这种方式使用 class 引用会使界面变得毫无意义。