Two questions. The first: is there a restriction that a class can only be extended by a single helper, after which it's the helper that has to be extended? i.e.
...
So if you want to completely cover the existing helper, don't use inheritance. But if you want to use methods from both helpers, use the inheritance:
Looking back through the record I can see that when class sealing was introduced I asked on the ML whether a sealed class could be extended by a helper.
Nobody had a confident answer to that, but I think it fair to also ask whether a chain of class helpers can be sealed to prevent anybody extending it further.
Of course, sealed classes can be extended by helpers. Example:
...
Sealing of classes are used only to block inheritance when creating a new data type (new class). Helpers are used to extend classes (and any other types of data), where inheritance does not occur at all, so the seal in this case does not matter.
Interestingly, it is not possible to seal the helper. Thus, each type can be extended with helpers, and their number is not limited. It is therefore possible to create a theoretically freely long chain of helper inheritance and extend the given type of data without end.
Two questions. The first: is there a restriction that a class can only be extended by a single helper, after which it's the helper that has to be extended? i.e.You can declare multiple helpers for a class, the compiler will simply pick the last one in scope. If you want to use multiple helpers you need to use inheritance.
A= class
B= class helper for A
C= class helper for A
is wrong, while
A= class
B= class helper for A
C= class helper(B) for A
is right? Alternatively, is there a rule that only one helper can be declared in a unit?
The problem that I was having was that when compiling using the Lazarus IDE it would fail at the first point it encountered a method from helper B, rather than getting into the unit B and saying "You can't declare C in here".
The second: Can the definition of a class list the names of the units in which it may be extended by a helper?Eh? What are you asking here?
You can declare multiple helpers for a class, the compiler will simply pick the last one in scope. If you want to use multiple helpers you need to use inheritance.
Also the compiler would not be able to detect that you extend class A (declared in unit A) in both units B and C (without dependencies on eachother) as those units could be compiled independently (or be precompiled), not to mention that you could use unit B in unit X and unit C in Y those using different helpers for A inside the same binary.
Please note that we're planning to add support for multiple helpers to be active at once. You can keep track of the progress here (https://bugs.freepascal.org/view.php?id=35159).
Mark, I hope you understand class helpers are a bandage (except maybe for simple types) and not a cure....Of course, sealed classes can be extended by helpers. Example:
...
Sealing of classes are used only to block inheritance when creating a new data type (new class). Helpers are used to extend classes (and any other types of data), where inheritance does not occur at all, so the seal in this case does not matter.
Interestingly, it is not possible to seal the helper. Thus, each type can be extended with helpers, and their number is not limited. It is therefore possible to create a theoretically freely long chain of helper inheritance and extend the given type of data without end.
Thanks for that. I did say nobody had, and this was a few years ago :-)
I tend to look at things from the point of view of an OS writer, but I'd have thought that being able to forcibly terminate a helper chain would be useful. Or alternatively the second part of my original question, which was whether helpers could be rejected if they weren't in a list of specified units- which is probably infeasible, since I can't think of anywhere that a list of units is significant except uses clauses.
MarkMLl
Mark, I hope you understand class helpers are a bandage (except maybe for simple types) and not a cure....
>> The second: Can the definition of a class list the names of the units in which it may be extended by a helper?
>
> Eh? What are you asking here?
Whether at the time of definition a class can have restrictions as to where helpers can be declared, e.g. that helpers for TObject can only be in known RTL units.
In practice I think that the existing dependency rules probably go a long way towards that, but I think that whether a chain of helpers can be sealed is still a fair question- and probably one that needs to be considered before any relaxation of the structure.
Trunk now also supports the modeswitch multihelpers which allows multiple helpers to be active at once for a single type.
Will it ever be supported?Considering that I added support for interface type helpers as well, I could add support for object as well... You can add a bug report if you want...
as it is now I am able to inherit from an existing helper to add on features. From what I understand this is not allowed inDelphi allows inheritance for class helper, but I saw no real reason to disallow it for record helper and type helper... :-X
Delphi.
In Delphi you can have only one helper and any additions must be done to that one helper where as in Fpc you can
inherit from an existing helper which I like a lot!
:)
Why not call them all "type helper" ?
I do not understand why there are so many different helpersBecause it was Delphi that introduced class helper and record helper. True, it was me that introduced type helper for primitive types, but with FPC 3.2.0 and newer it's possible to use type helper with classes and records as well, so for me type helper is the definite syntax for helper types (though the other two will be available no matter what).
Why not call them all "type helper" ?
True, that would be enough, but we'd need to support the other syntax anyway due to Delphi compatibility. The type helper syntax on the other hand is a close enough extension.
type TFoo = class(TBar) // or any other type {..} end; type // instead of: TFooHelper = class helper for TFoo TFooHelper = helper(TFoo) {..} end; type // instead of: TFooHelper2 = class helper(TFooHelper) for TFoo TFooHelper2 = helper(TFooHelper) // or TFooHelper2 = helper(TFoo, TFooHelper) {..} end;
This should be enough. 8)
So, is there a\another hacking \ bandage for TClasses in order to bypass this behavior (i.e. create private fields), or do I have to create a descendant i.e. Class(TFoo) (that said, I've got the source code of TFoo; so, it's mostly curiosity)?