父过程如何调用被自身覆盖的子过程?
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
调用了since并text
设置了变量。
但是,当我打电话时,child.doThis
它只会显示一个空对话框,因为child.doThis
打电话parent.doThis
然后是??.BtnRefreshClick
。如何parent.doThis
拨打电话child.BtnRefreshClick
?不可能吗
在此先感谢
Yohan W.
父类调用基类的方法,因为这是存在于父类范围内的唯一方法。编译器编译TParent
代码时,它将名称绑定BtnRefreshClick
到基类中的方法,而不是子类中的方法,因为子类不是父类的祖先。
通常,对于父对象调用子类的方法,该方法应在父对象(或更高版本)中声明并且为virtual。如果更改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的答案所示,即调用相关按钮的Click
方法。当TChild
实例化表单上的按钮时,VCL读取DFM资源并找到与按钮OnClick
事件关联的字符串“ BtnRefreshClick” 。它使用表单的MethodAddress
功能查找具有该名称的方法的地址,并找到属于的方法的地址TChild
。它将该值分配给OnClick
属性。该Click
方法读取该属性并调用那里的任何方法。
我之前已经写过关于直接调用事件处理程序方法,调用event-handler属性和调用事件触发器之间的区别,但是那时,我还没有考虑此处所示的隐藏处理程序的方面。或在子孙类中被覆盖。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句