我有一个定义为:
的类TfraFrame = class(TFrame);
然后我有几个子类,从这里开始,例如:
TfraUsers = class(TfraFrame);
TfraGroups = class(TfraFrame);
TfraMenus = class(TfraFrame);
在我的主要表单中,我将变量声明为:
var
fraUsers: TfraUsers;
fraGroups: TfraGroups;
fraMenus: TfraMenus;
现在我的问题是,我希望有一个单独的函数来控制每个类的实例的生成。每个类只应该有一次实例,但我只想在用户需要时创建实例。
我想传递这样的变量:
procedure ShowFrame(Frame: TfraFrame)
begin
if Frame = nil then
begin
Frame := TfraFrame.Create(self);
Frame.Init(Panel1);
end;
Frame.Show;
end;
并像这样称呼它;
ShowFrame(fraUsers);
我原本期望它创建TfraUsers
的实例(因为这是fraUsers
被声明为的实例),但是,我怀疑它可能正在创建fraFrame
的实例。 / p>
有没有办法创建变量被声明为的类型的实例?
答案 0 :(得分:3)
是的,你需要告诉showFrame要实例化哪个类:
添加
type
tfraFrameClass = class of TfraFrame;
宣布tfraFrame之后。并将showFrame更改为:
function ShowFrame(Frame: TfraFrame; FrameClass: TfraFrameClass): TfraFrame;
begin
if Frame = nil then
begin
Result := FrameClass.Create(self);
Result.Init(Panel1);
end
else
Result := Frame;
Result.Show;
end;
请注意,您不能将Frame作为var参数传递,因为编译器将坚持声明的和实际类型的传递参数完全相同。
<强>更新强> 更新了示例,以便在已经分配帧时显示帧。
<强>更新强> 我忽略了提到在showFrame过程的OP代码中分配Create调用的结果是行不通的。如果未将其声明为var,则赋值不会超出showFrame过程的范围,传递给showFrame的变量值将不会更改。如上所述,将其声明为var将不起作用。解决方案是做@Andreas建议的:使用无类型指针;或者让它像我一样发挥作用。当然(咧嘴笑)我更喜欢我的,因为它可以更好地保护类型安全。
另外,当然在我的例子中,目的是将showFrame函数的结果分配给适当的帧变量,如下所示:
fraUsers := showFrame(fraUsers, TfraUsers);
<强>更新强> 或者,正如Sertac指出的那样,当您对传递给showForm的变量进行强制转换时,仍然可以使用带有var参数的过程。
procedure showFrame(var Frame: TfraFrame; FrameClasse: TfraFrameClass);
begin
if Frame = nil then
begin
Frame := FrameClass.Create(self);
Frame.Init(Panel1);
end;
Frame.Show;
end;
并将其命名为:
showFrame(TfraFrame(fraUsers), TFraUsers);
答案 1 :(得分:0)
我建议您制作框架变量属性
property fraUsers: TfraUsers read GetfraUsers write ffraUsers;
..
function GetFraUsers: TFraUsers;
begin
if fFraUsers = nil then
fFraUsers := TfraUsers.Create(...);
Result := ffraUsers;
end;
Then
procedure ShowFrame(Frame: TfraFrame)
begin
Frame.Init(Panel1);
Frame.Show;
end;
procedure form1.Button1Click(...)
begin
ShowFrame(fraUsers); // creates the frame if it does not exist
end;