Class helper doesn't override ancestor's virtual methods
Asked Answered
S

2

5

I always understood class helpers as extension classes, or partial classes. They act like an expand for the code of the original base class. If I copied the interface part of code and add it to the base class and do so for the implementation too, the code will run perfectly the same way as with the helper. This let me always understand the polymorphisme in helpers and why they can't override methods from the base class and such things.

But I found that this is not completely true, because if so then why they don't allow to override methods of an ancestor -parent of the base- class?

Here is an example of what I mean(I will only put the code for the headers without implementation code):

type
  TAncestor = class
  public 
    procedure Test; virtual;
  end;

  TBase = class(TAncestor)
  public 
  end;

So why the next code is not right :

THelper = class helper of TBase
public 
  procedure Test; override;
end;

The error that I have is :

Method 'Test' not found in base class!

Surakarta answered 13/3, 2019 at 14:25 Comment(3)
Helpers are fitted on at the side. They just extend the name space. To override a virtual method you need to subclass.Niels
@DavidHeffernan actually i am subclassing, TBase is a subclass of TAncestor...Surakarta
You need to subclass TBase rather than extend TBase. Or override the method in TBase.Niels
S
10

Class helpers can not modify the original class layout. That is why they can't add fields (but they can add non-virtual non-dynamic methods, of course). The extra methods are not really part of the helped class, they merely tell the compiler that each time it sees that method, it should pretend it was part of the original class

But overriding a virtual method would mean modifying the virtual method table of the helped class, and that is not possible either. The compiler could of course create a new VMT (an array of pointers to code) with the override in it, but, because a class helper does not modify the "helped" instance, it can't simply replace the VMT pointer in the instance with the new one. So the instance cannot be made to refer to the new VMT.

There is only one way to override a virtual method: by inheritance.

Documentation says:

A helper type may not declare instance data, but class fields are allowed.

Susannahsusanne answered 13/3, 2019 at 14:35 Comment(9)
actually what class helpers do is that they modify the original layout and they add fields, and what i want is that the compiler pretend that the overriden method was part of the original class, notice that i am not overriding an original class field, but the anscestor's one...Surakarta
@Surakarta Completely wrong. Helpers cannot add fields. Also, consider if two different units provided helpers for this class and could provide an override. Which method would be called?Niels
sorry i meant adding methods, anyway this doesn't has anything to do with my case, what if the two helpers in the different units added a field with the same name, which one would be called?Surakarta
They cannot add fields, only methods (and still not override those, only add methods). And you can have only one helper at the same time, so it depends which one is closest in scope.Denunciate
@Surakarta My question of the two helpers is very relevant. If you were able to do what you ask, contemplate which helper would win? Remember that you might be making a call on a reference typed as TAncestor at a point in the code where no helper was visible?Niels
@ZORRO_BLANCO: no, they don't.Susannahsusanne
as i said "sorry by field i meant method" -which is wrong-, and my question has nothing to do with fields but thanks for the answerSurakarta
A virtual method requires a field in the VMT, as I explained. Even if you had a new VMT, the original class VMT pointer would not point to it, so overriding virtual methods is not possible.Susannahsusanne
@RudyVelthuis Aha, this last info was the key i guess, i didn't know that a virtual method requires a field, and i didn't understand that from your answer, i think it will be helpfull if you add it to the answer :) thanks again and please execuse my bad english understandingSurakarta
N
4

try "class interception" (ggl it)
something like this its similar to c# "partial class" in delphi

type
  TPageControl = class(Vcl.ComCtrls.TPageControl)
....
Nanoid answered 28/10, 2019 at 14:44 Comment(1)
Na verdade isso se chama "Interposer Class"Myrtamyrtaceous

© 2022 - 2024 — McMap. All rights reserved.