On 30.01.2011 09:03, Hans-Peter Diettrich wrote:
Paul Ishenin schrieb:

For some reason the visibility is completely ignored here. I can add a
class helper to the strict private or even move it to another unit -
it is always visible.

IMO class helper methods always should become visible as part of the
class, regardless of where they are declared.

 From the Delphi wiki:

"You can define and associate multiple helpers with a single type.
However, only zero or one helper applies in any specific location in
source code. The helper defined in the nearest scope will apply. Class
or record helper scope is determined in the normal Delphi fashion (for
example, right to left in the unit's uses clause)."

I.e. a single Helper reference (field) in the class definition is
sufficient. This field cannot be persistent, instead it has to be
initialized for every use case: whenever a helper is found in the
compiled unit, or in one of its used units, it overwrites the Helper
reference. Adding the helper elements to the class STB is not a valid
solution, because another helper can become active at any time, during
compilation.

The ancestors of the Helper class must be searched as well.


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

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.


Also:

"Note that the class helper function MyFunc is called, because the class
helper takes precedence over the actual class type."

That's bad, because this disallows to treat the helper like an ancestor,
accessible in all derived classes :-(


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

==== source begin ====
type
  TFoo = class
  end;

  TFooHelper = class helper for TFoo
  end; // this helper only applies to variables of type TFoo

  TBar = class(TFoo)
  end; // No methods of TFooHelper are available for variables of this type

  TBarHelper = class helper(TFooHelper) for TBar
end; // now all methods of TFooHelper (that aren't overriden by TBarHelper) are available for all variables of type TBar as well
==== source end ====

Interesting questions:

1) Unit A defines an class helper for TFoo, then uses in the
implementation section unit B, which also defines an helper for TFoo.
According to the above rules the helper in A should become inaccessible
and useless then.


This is indeed something that I need to test. And I hope that Delphi behaves the way you described (because that would be the consistent behavior)

2) Similarly multiple class helpers can be defined in the implementation
section, which are used in the immediately following code, until the
next helper declaration.


Needs to be tested as well, but I hope so.

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 ====

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.

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. 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.

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

Reply via email to