Delphi (德尔菲)呼叫Child';来自家长的程序

Delphi (德尔菲)呼叫Child';来自家长的程序,delphi,overriding,Delphi,Overriding,父过程如何调用从自身重写的子过程 type TBase = class(TForm) procedure BtnRefreshClick(Sender: TObject); protected text: string; end; procedure TBase.BtnRefreshClick(Sender: TObject); begin showmessage(text); end; 实际调用过程类似于: child := TChild.Create; ch

父过程如何调用从自身重写的子过程

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

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



实际调用过程类似于:

child := TChild.Create;
child.doThis;

如果我尝试执行
child.btnRefresh,请单击然后它将生成一个对话框<代码>你好,世界因为调用了
TChild.BtnRefreshClick
并设置了
text
变量

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

提前感谢,

Yohan W.

如@StefanGlienke所述,使用
btnRefresh。单击

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;

谢谢

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

通常,对于要调用子类的方法的父对象,该方法应该在父对象(或更高级别)中声明,并且是虚拟的。如果更改
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设置按名称分配方法属性的表单的特定情况下,另一种解决方案如所示,即调用关联按钮的
单击
方法。当实例化
TChild
表单上的按钮时,VCL读取DFM资源并找到与按钮的
OnClick
事件相关联的字符串“BtnRefreshClick”。它使用表单的函数查找具有该名称的方法的地址,并找到属于
TChild
的地址。它将该值分配给
OnClick
属性。
Click
方法读取该属性并调用其中的任何方法


我以前写过,但当时,我没有考虑此处所示的方面,即在子类中隐藏或重写处理程序。

您所说的与您的代码不匹配。如果实例是一个TChild,那么doThis将调用TChild.Clicky,因为此方法是虚拟的并被重写。而且,当你们谈论两种不同的方法时,我只看到一种。@StefanGlienke:不太可能
clicky
实际上是TParent父类上的
TdxBarButton.onClick
事件<代码>点此
是我在TParent类中声明并从TChild调用的自定义受保护虚拟过程。您可以通过一个简单的Web搜索来回答这个问题。请不要认为这会取代websearch。但这完全是毫无意义的链接伪代码。不要这样做。BtnRefreshClick显然是btnRefresh的事件处理程序,您正在使用表单继承。可以将BtnRefreshClick方法标记为虚拟(未测试),也可以只调用btnRefresh。单击可触发正确的事件处理程序。@StefanGlienke:是的,已解决。只需按照您所说的调用
btnRefresh。单击
而不是
btnRefresh单击(nil)
。非常感谢@戴维德费弗南:好吧,那么我就请你别再问了,因为我的问题还不够好,不能在SO上显示出来。请注意,当您有一个不同的
OnABC
事件,其中组件没有可以调用的
ABC
方法时,@StefanGlienke建议使用
MyControlABC
方法(在您的情况下,
BtnRefreshClick
)子类中的
virtual
one和override每个
MyControlABC
也可以工作。我希望我们这里有一个像约翰·斯基特这样的人。他有代表性和礼貌,有助于积极鼓励人们写出更好的问题和答案。谢谢你的坚持@据我理解,杰罗恩的评论是针对我的。我不认为告诉提问者他们的问题是好的,而他们不是。即使是现在,它也有破解和伪造的代码。当他们问什么是SSCCE时,我认为应该鼓励他们进行网络搜索。我从以前的评论中知道,你更喜欢为他们做网络搜索,并提供链接和总结这些链接。我不认为忽视不好的问题,让提问者继续认为这样问是好的that@Jeroen如果一个同事带着假代码来找我,他们会被送走,并被告知带着真代码回来。他们会这么做的。“他们不会再犯两次错误了。”大卫,这不是针对你的。这是针对德尔福社区,让更多的人在这里以积极的方式指导人们更好地撰写问题和答案。我已经指导了很多客户编写更好的代码。不是针对他们的错误,而是从他们做得好的事情开始并从中改进。这真的很有效,现在他们中的一些人也帮助指导其他人。saintfalcon从一开始就写了一个问题,做得很好。@Jeroen我同意这一点,但我认为这种方法可能走得太远了。如果人们没有被告知他们的问题出了什么问题,那么有什么动机去改进呢?同样,如果人们编辑问题来改进它们。这里的提问者确实很努力,但是原始问题中的代码离问题太远了,很难补救。外卖消息是编写一个SSCCE,并在发布前立即对其进行测试。Tbc。很高兴你从其他评论中做出了这个回答。谢谢谢谢你更详细地解释。
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;
type
  TBase = class(TForm)
    procedure BtnRefreshClick(Sender: TObject); virtual;
  end;

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