[Lazarus] Generics type as parameter

Sven Barth pascaldragon at googlemail.com
Sat May 12 17:00:22 CEST 2012


On 12.05.2012 13:32, Leonardo M. Ramé wrote:
> I'm trying to work in an abstract way with generics, I need to create a
> method receiving a un-specialized generic and do some work on it.
>
> Example:
>
> function ProcessGeneric(AList: TFPGList);
> begin
>    ... do something ...
> end;
>
> Imagine your application uses many lists of specialized objects, such as
> TCustomer, TBooks, TColors. To create a list of those types, you'd do
> something like this:
>
>    TCustomers = specialize TFPGList<TCustomer>;
>    TBooks = specialize TFPGList<TBook>;
>    TColors = specialize TFPGList<TColor>;
>
> Then, you need to pass any of those types to "ProcessGeneric":
>
> var
>    lCustomers: TCustomers;
>    lBooks: TBooks;
>    lColors: TColors;
>
> begin
>    ProcessGeneric(lCustomers);
>    ProcessGeneric(lBooks);
>    ProcessGeneric(lColors);
> end;
>
> Without generics, I can use, for example, a TObjectList, or a
> TCollection, without any problem. Is there a way to do this using
> Generics?.

There are basically to ways you can achive this (one is supported by FPC 
the other not yet):
* descend the generic from a baseclass you can work with (e.g. as 
Michalis already mentioned the FGL classes all descend from a baseclass 
that is tailored to the needs of the generic, e.g. TFPGList descends 
from TFPSList)
* use generic procedures (this is not yet supported with FPC, it's on my 
ToDo list though).

In case of generic procedures your example will then look like this (in 
mode Delphi):

=== example begin ===

procedure ProcessGeneric<T>(AList: TFPGList<T>);
begin
   ...
end;

var
    lCustomers: TCustomers;
    lBooks: TBooks;
    lColors: TColors;

begin
    ProcessGeneric<TCustomer>(lCustomers);
    ProcessGeneric<TBook>(lBooks);
    ProcessGeneric<TColor>(lColors);
end;

=== example end ===

(in mode ObjFPC there would be a bit more "generic" and "specialize" of 
course)

In mode Delphi you can also use a workaround in the current version 
(2.7.1) of FPC (it should work at least, but I haven't tested it...):

=== workaround begin ===

TMyListProcessor<T> = class
   class procedure ProcessGeneric(AList: TFPGList<T>);
end;

class procedure TMyListProcessor<T>(AList: TFPGList<T>);
begin

end;

var
    lCustomers: TCustomers;
    lBooks: TBooks;
    lColors: TColors;

begin
    TMyListProcessor<TCustomer>.ProcessGeneric(lCustomers);
    TMyListProcessor<TBook>.ProcessGeneric(lBooks);
    TMyListProcessor<TColor>.ProcessGeneric(lColors);
end;

=== workaround end ===

This won't work as written above in mode ObjFPC (yet), because you'd 
always need to specialize the class in a type section.

Regards,
Sven




More information about the Lazarus mailing list