[fpc-devel] Status report for "class helpers"

Hans-Peter Diettrich DrDiettrich1 at aol.com
Mon Jan 31 01:51:39 CET 2011

Sven Barth schrieb:

> Sorry, I don't understand what you want to tell here.

Sorry2, I'll retry.

> I personally expect a class helper that is defined inside a private 
> section of a class not to be available in another unit like I can't 
> access a field or another type defined in there as well.

Delphi allows for *at most* one active class helper, determined by the 
unit search order, just like every other ambiguous identifier is 
resolved. If you don't want an class helper used in other units, simply 
move it to the implementation section.

Hiding an class helper in a private section of a class IMO is not the 
right way, and the result may be compiler specific.

> If you want to have a class helper available in a derived class there is 
> only one way to do this:

Okay, now I understand the use of one ancestor, but still not the use of 
a list of ancestors.

>> 3) What about derived classes? Since derived classes are compiled
>> independently, they never will use a reintroduced method in an class
>> helper.
> This is correct. The following does not work in Delphi:
> ==== source begin ====
> type
>   TStringsHelper = class helper for TStrings
>     procedure Test;
>   end;
> var
>   s: TStringList;
> begin
>   s.Test; // this won't work
>   TStrings(s).Test // but this does
> end;
> ==== source end ====

This looks very much like my #4.

>> 4) When class helpers are evaluated at compile time, according to the
>> static object types (like properties are), then they could be handled
>> just like the well known typecast hack:
>> type TMyFoo = class(TFoo)
>> <helper methods>
>> end;
>> with following casts of every TFoo reference into TMyFoo.
>> But TFoo derived types must be handled in the same way, so that I see no
>> way around an extended search inside the TFoo STB.
> Technically class helpers ARE classes that derive from the extended 
> class (here: TFoo). But there are no casts of TFoo references. When 
> searching for a symbol in a class the last class helper in scope for 
> that class is searched first and then the symbol is searched in the 
> class itself.

Then one possible implementation could hide the extended class (TFoo), 
and use the helper class STB instead. This were the implementation of an 
implicit type cast. The symtable stack has to be built or modified 
accordingly, so that searching continues in the proper class ancestors.

>> 5) What's the meaning of the "ancestor list"? IMO interfaces cannot be
>> added by an class helper, and multiple inheritance is quite unlikely.
>> Will the ancestor list allow to override interface *implementations*?
> I don't know how you come to interfaces now.

This is the normal use of a *list* of ancestors. The first ancestor 
denotes the parent class, all others denote interfaces.

> But basically from the 
> outside class helpers seem to support multiple inheritance, but 
> technically they don't. It works like this:
> * the extended class is the real parent of the class helper class
> * if the class helper has a parent ( e.g. class helper(TFooHelper) for 
> TFoo ) this parent is referenced in a mostly unimportant "helperparent" 
> field of tobjectdef and only used when searching for a symbol.
> At the end the pseudo parent of a class helper tells the compiler to 
> search the symbol table of that class helper as well.

See above.

I'd push the extended class onto the symtable stack, then the class 
helper parents, and finally the class helper itself, and use that stack 
whenever a reference to a class with a helper class is encounterd.


More information about the fpc-devel mailing list