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.

DoDi

_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to