(Delphi)从Parent调用Child的程序

时间:2014-03-24 17:59:27

标签: delphi override

父程序如何调用它自己的子程序?

type
  TBase = class(TForm)
  procedure BtnRefreshClick(Sender: TObject);
  protected
    text: string;
end;

procedure TBase.BtnRefreshClick(Sender: TObject);
begin
  showmessage(text);
end;

type
  TParent = class(TBase)
  protected
    procedure doThis;
  end;

procedure TParent.doThis;
begin
  // blah blah do something
  BtnRefreshClick(nil);
end;

type
  TChild = class(TParent)
  procedure BtnRefreshClick(Sender: TObject);
  protected
    procedure clicky; override;
  end;

procedure TChild.BtnRefreshClick(Sender: TObject);
begin
  text := 'Hello, World!';
  inherited;
end;

实际调用程序有点像:

child := TChild.Create;
child.doThis;

如果我尝试child.BtnRefreshClick;,那么在调用Hello, World!并设置TChild.BtnRefreshClick变量后,它会生成text的对话框。

但是,当我致电child.doThis时,它只会显示一个空对话框,因为child.doThis会调用parent.doThis然后调用??.BtnRefreshClick。如何parent.doThis致电child.BtnRefreshClick?这不可能吗?

提前致谢,
Yohan W。

2 个答案:

答案 0 :(得分:6)

父类调用基类的方法,因为这是父类范围内存在的唯一方法。当编译器编译TParent代码时,它将名称BtnRefreshClick绑定到基类中的方法,而不是子类中的方法,因为子类不是父类的祖先。 / p>

通常,对于父对象来调用子类的方法,该方法应该在父对象(或更高版本)中声明,并且是虚拟。如果您将TBase更改为BtnRefreshClick虚拟,并将TChild更改为覆盖相同的方法,那么当TParent.doThis调用它时,将被发送到TChild方法。

type
  TBase = class(TForm)
    procedure BtnRefreshClick(Sender: TObject); virtual;
  end;

  TChild = class(TParent)
    procedure BtnRefreshClick(Sender: TObject); override;
  end;

在通过DFM设置按名称分配方法属性的表单的特定情况下,另一个解决方案是Saintfalcon's answer演示,即调用关联按钮的Click方法。当实例化TChild表单上的按钮时,VCL读取DFM资源并找到与按钮的OnClick事件关联的字符串“BtnRefreshClick”。它使用表单的MethodAddress函数来查找具有该名称的方法的地址,并找到属于TChild的地址。它将该值分配给OnClick属性。 Click方法读取该属性并调用其中的任何方法。

我之前写过关于the differences between calling an event-handler method directly, calling the event-handler property, and calling the event trigger的文章,但当时我还没有考虑过这里所示的方面,其中处理程序在后代类中被隐藏或覆盖。

答案 1 :(得分:3)

如@StefanGlienke所述,使用btnRefresh.click

procedure TParent.doThis;
begin
  // blah blah do something
  // BtnRefreshClick(nil); // this will call TBase.BtnRefreshClick
  btnRefresh.Click; // use this instead to call TChild.BtnRefreshClick
end;

谢谢