[fpc-devel] RFC: Delphi style class helpers

Jonas Maebe jonas.maebe at elis.ugent.be
Tue Dec 21 11:04:06 CET 2010


On 21 Dec 2010, at 10:13, Sven Barth wrote:

> Am 21.12.2010 00:16, schrieb Jonas Maebe:
>>
>> Note that Delphi-style class helpers have several limitations that  
>> still have to be added to your patch:
>> a) from http://docwiki.embarcadero.com/RADStudio/2010/en/Class_and_Record_Helpers 
>>  : "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)." -- In Objective-C, there is no limit on the number  
>> of categories for a class that applies at the same time.
>
> I don't know whether we should really follow this limitation (and  
> when, then only in mode Delphi)

I would suggest asking on the Embarcadero forums what the reason is  
for this limitation. It would be annoying to have to add to wiki/ 
User_Changes_2.6.2 "Disabled multiple class helpers for a single class  
because it breaks/conflicts with/... X", like we have had to do  
already with several other cases where we removed what we considered  
to be useless limitations of Delphi features. The fact that it works  
in Objective-C/Pascal does not mean that it also fits to Object  
Pascal, because both languages are quite different (and because  
Objective-C/Pascal has a complex runtime system that does a lot of  
things behind your back).

Regarding some of the other limitations mentioned earlier: it seems  
that in Delphi 2010, you can add virtual methods to a class helper: http://windwings.wordpress.com/2009/10/07/turbocharging-delphi-2010-adding-dynamic-functionality-to-3rd-party-frameworks-read-vcl/ 
. You cannot override any methods of a helped class, but you can  
override virtual methods defined in one class helper in a class helper  
that inherits from it. Apparently support for class constructors/ 
destructors has also been added to class helpers.

This feature (virtual class helper methods) might be part of the  
reason why only one class helper can be used, depending on how they  
handle the class helper VMTs. You start getting some kind of multiple  
inheritance with multiple VMTs in terms of figuring out which class  
helper VMT to pass when calling one class helper method from another  
class helper.

Take this example:

*** unit1:

type
   tclasshelperbase = class helper for tobject
     procedure test; virtual;
   end;

   ttestcaller = class helper for tobject
     procedure calltest;
   end;


procedure tclasshelperbase.test;
   begin
     writeln('in base');
   end;

procedure ttestcaller.calltest;
   begin
     test;
   end;

*** unit 2:

type
   tclasshelperderived = class helper(tclasshelperbase) for tobject
     procedure test; override;
   end;

procedure tclasshelperderived.test;
   begin
     writeln('in derived');
   end;

*** main program:
uses
   unit1, unit2;
var
   o: tobject;
begin
   o:=tobject.create;
   o.calltest;
end.

Now which "test" should be called from ttestcaller.calltest? Since  
both unit1 and unit2 are in scope, I'd assume  
tclasshelperderived.test. But how does ttestcaller.calltest get the  
VMT of tclasshelperderived? Do you pass a linked list or array of VMTs  
of all class helper hierarchies currently in scope to all class helper  
routines, which then walk this list/array every time in search for the  
appropriate VMT to use?


Jonas



More information about the fpc-devel mailing list