Delphi - 创建子类的实例

时间:2010-08-22 14:43:39

标签: delphi oop

我有一个定义为:

的类
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>

有没有办法创建变量被声明为的类型的实例?

2 个答案:

答案 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;