Difference between revisions of "Helper types"
(first version of class helper page)
m (Class helpers moved to Helper types: The topic should describe both class helpers and record helpers at once (as there are only subtle differences between them))
Revision as of 16:51, 13 April 2011
Class helpers allow you to define new functionality for classes. This is useful if you can't extend a class because it's sealed or you can't control of which final type the class instance is (e.g. Lines/Items properties in various LCL components). This page describes class helpers in Object Pascal. For class helpers in Objective Pascal see here.
If you want to test this feature you need to checkout a FPC branch using the following command:
svn checkout http://svn.freepascal.org/svn/fpc/branches/svenbarth/classhelpers fpc-classhelpers
You can build the compiler like a normal trunk compiler (you should use FPC 2.4.2 for building of course).
This is a Work In Progress and thus not everything described here might work that way in the compiler or even work at all.
The syntax for class helpers is the following: <delphi> ClassHelperName = class helper[(BaseClassHelper)] for ExtendedClass
[properties, procedures, functions, constructors]
end [hint modifiers]; </delphi>
ClassHelperName, BaseClassHelper and ExtendedClass have to be valid Pascal identifiers, BaseClassHelper must be a class helper for a super class of ClassHelperName and ExtendedClass must be an Object Pascal class or record (the latter is not supported yet in FPC). The declarations inside a class helper are very similiar to a normal class declaration, but you must not use fields and destructors.
You can not reference class helpers anywhere in the code except when inheriting from one. The methods are always available once its unit is used and can be called as if they'd belong to the extended class.
Example: <delphi> type
TObjectHelper = class helper for TObject function TheAnswer: Integer; end;
function TObjectHelper.TheAnswer: Integer; begin
Result := 42;
o := TObject.Create; o.TheAnswer;
A class helper may not
- contain (class) destructors
- contain (class) fields
- contain abstract methods
- "override" virtual methods of the extended class (they can be hidden by the helper though)
If a class helper has a constructor the first statement in that constructor must be a call to the parameterless constructor.
- PascalDragon 21:51, 28 January 2011 (CET): This statement needs to be verified. I've found an example where this was not the case.
TObjectHelper = class helper for TObject constructor SomeMagicCreate(aFoo: Integer); end;
constructor TObjectHelper.SomeMagicCreate(aFoo: Integer); begin
Create; // must be the first statement!
Methods of the extended class can be overloaded (in mode ObjFPC this is enabled by default, in mode Delphi you must enable this by using the overload keyword).
- PascalDragon 21:51, 28 January 2011 (CET): This is not yet working in any of both modes.
<delphi> TObjectHelper = class helper for TObject
function ToString(const aFormat: String): String; overload;
function TObjectHelper.ToString(const aFormat: String): String; begin
Result := Format(aFormat, [ToString]);
Writeln(o.ToString('The objects name is %s'));
A class helper can inherit for another class helper if it extends a subclass of the class which is extend by the parent class helper.
Example: <delphi> TObjectHelper = class helper for TObject
TFoo = class(TObject) end;
TFooHelper = class helper(TObjectHelper) for TFoo end; </delphi>
This allows you to use class methods that where added for a super class with a child class as well. E.g. you have a class helper that is defined for a TStrings, but you have a TStringList variable and don't want to cast to TStrings every time you want to use the helper method.
Differences between mode Delphi and ObjFPC
In mode Delphi you can use virtual, dynamic, override and message identifiers. As the concepts behind those identifiers (virtual methods, message dispatching) isn't applicable for class helpers, those keywords are ignored in mode Delphi and not allowed in mode ObjFPC. On the other hand you need to define "overload" in mode Delphi if you want to introduce a method with the same name as the original one without hiding it. In mode ObjFPC you don't need this (the same way as in normal classes).
The following table lists some examples for class helpers found on the web and whether they work with the current implementation.
|Class helper to add for ... in support for TComponent.Components / ComponentCount||ok|
|Class helper for Delphi's TStrings: Implemented Add(Variant)||ok|