类助手没有覆盖祖先类的虚拟方法。

4
我一直理解类助手作为扩展类或部分类。它们的作用就像是对原始基类代码的扩展。如果我将代码的接口部分复制并添加到基类中,然后对实现部分也这样做,那么代码将完全以同样的方式运行,就像使用助手一样。这让我一直理解助手中的多态性,并且它们不能覆盖基类的方法和其他类似的事情。
但是我发现这不是完全正确的,因为如果是这样的话,为什么它们不允许覆盖祖先类-父类的方法呢?
下面是我指的示例(我只会放置标题的代码,不包括实现代码):
type
  TAncestor = class
  public 
    procedure Test; virtual;
  end;

  TBase = class(TAncestor)
  public 
  end;

那么,为什么下面的代码不正确:
THelper = class helper of TBase
public 
  procedure Test; override;
end;

我遇到的错误是:

在基础类中找不到方法 'Test'!


1
Helpers 被安装在侧面。它们只是扩展名称空间。要覆盖虚拟方法,您需要子类化。 - David Heffernan
@DavidHeffernan 实际上,我正在进行子类化,TBase 是 TAncestor 的一个子类... - ZORRO_BLANCO
你需要对TBase进行子类化而不是扩展TBase。或者在TBase中重写该方法。 - David Heffernan
2个回答

9
类助手无法修改原始类的布局,这就是为什么它们不能添加字段(但它们当然可以添加非虚拟的非动态方法)。额外的方法实际上并不是帮助类的一部分,它们只是告诉编译器,每次它看到该方法时,应该 假装 它是原始类的一部分。
但覆盖虚拟方法意味着修改帮助类的虚拟方法表,这也是不可能的。编译器当然可以创建一个新的VMT(指向代码的指针数组),其中包含了覆盖的内容,但由于类助手不会修改 "帮助" 实例,因此它不能简单地用新的VMT指针替换实例中的VMT指针。因此实例无法引用新的VMT。
唯一的覆盖虚拟方法的方式是通过继承。 文档 表示:

助手类型不能声明实例数据,但允许类字段。


4
完全错误,帮助程序无法添加字段。此外,请考虑如果两个不同的单位为该类提供了帮助程序并且可以提供覆盖。哪种方法会被调用? - David Heffernan
1
他们无法添加字段,只能添加方法(但仍然不能覆盖那些方法,只能添加新的方法)。而且你同时只能有一个帮助器,所以取决于哪一个范围最接近。 - GolezTrol
1
@ZORRO_BLANCO 我的两个帮手问题非常相关。如果您能够做到您所要求的,考虑哪个帮手会获胜?请记住,在代码中没有任何帮手可见的情况下,您可能会对一个被标记为“TAncestor”的引用进行调用。 - David Heffernan
1
@ZORRO_BLANCO:不,他们不会。 - Rudy Velthuis
1
@RudyVelthuis 啊哈,我猜这个最后的信息是关键,我不知道虚方法需要一个字段,也没有从你的回答中理解到,如果您能把这个加入到答案中,那将会很有帮助 :) 再次感谢,请原谅我的英语理解能力。 - ZORRO_BLANCO
显示剩余4条评论

4

尝试搜索“类拦截”(谷歌一下)
类似于C#中的“partial class”,在Delphi中也有类似的功能。

type
  TPageControl = class(Vcl.ComCtrls.TPageControl)
....

1
实际上,这被称为“Interposer Class”。 - Carlos B. Feitoza Filho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接