A generic class definition is much like a class definition, with the exception that it contains a list of
placeholders for types, and can contain a series of local variable blocks or local type blocks, as can be
seen in the following syntax diagram:
The generic class declaration should be followed by a class implementation. It is the same as a normal
class implementation with a single exception, namely that any identifier with the same name as one of
the template identifiers must be a type identifier.
The generic class declaration is much like a normal class declaration, except for the local variable and
local type block. The local type block defines types that are type placeholders: they are not actualized
until the class is specialized.
The local variable block is just an alternate syntax for ordinary class fields. The reason for introducing is
the introduction of the Type block: just as in a unit or function declaration, a class declaration can now
have a local type and variable block definition.
The following is a valid generic class definition:
Type
generic TList<_T>=class(TObject)
type public
TCompareFunc = function(const Item1, Item2: _T): Integer;
var public
data : _T;
procedure Add(item: _T);
procedure Sort(compare: TCompareFunc);
end;
This class could be followed by an implementation as follows:
procedure TList.Add(item: _T);
begin
data:=item;
end;
procedure TList.Sort(compare: TCompareFunc);
begin
if compare(data, 20) <= 0 then
halt(1);
end;
There are some noteworthy things about this declaration and implementation:
- There is a single placeholder _T. It will be substituted by a type identifier when the generic class
is specialized. The identifier _T may not be used for anything else than a placehoder. This means
that the following would be invalid:
procedure TList.Sort(compare: TCompareFunc);
Var
_t : integer;
begin
// do something.
end;
- The local type block contains a single type TCompareFunc. Note that the actual type is not yet
known inside the generic class definition: the definition contains a reference to the placeholder _T.
All other identifier references must be known when the generic class is defined, not when the
generic class is specialized.
- The local variable block is equivalent to the following:
generic TList<_T>=class(TObject)
type public
TCompareFunc = function(const Item1, Item2: _T): Integer;
Public
data : _T;
procedure Add(item: _T);
procedure Sort(compare: TCompareFunc);
end;
- Both the local variable block and local type block have a visibility specifier. This is optional; if it
is omitted, the current visibility is used.