父程序如何调用它自己的子程序?
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。
答案 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;
谢谢