8.2 Определение дженерика классов |
Вверх Предыдущий Следующий |
Объявление дженерика очень похоже на определение типа, за исключением того, что он должен содержать список типов заполнителей (шаблонов), как показано на следующей синтаксической диаграмме: Дженерик классов Для классов, объектов, процедурных типов и расширенных записей, объявление дженерика должно сопровождаться его реализацией. Это то же самое, что и обычная реализация класса, кроме того что, имя идентификатора шаблона, должен быть именем типа (класса, записи оди простого типа). Таким образом, объявление типа дженерика очень похоже на объявление обычного типа, но в объявлении присутствует неопределённый тип. Неопределённые типы перечислены в списке, и они неопределены , пока класс не специализируется. Ниже приведено допустимое определение дженерика: 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; Класс может быть реализован следующим образом: procedure TList.Add(item: _T); begin data:=item; end;
procedure TList.Sort(compare: TCompareFunc); begin if compare(data, 20) <= 0 then halt(1); end; В этом объявлении и реализации есть некоторые особенности: 1.Заполнитель _T будет заменен именем уточнённого типа, когда дженерик будет специализирован. Идентификатор _T не может использоваться для чего - нибудь другого, кроме заполнителя типа. Что значит, что следующий код неверен: procedure TList.Sort(compare: TCompareFunc); Var _t : integer;
begin // какие-то действия end; 2.Блок локальных типов содержит единственный тип TCompareFunc. Обратите внимание, что фактический тип не известен при определения дженерика: определение содержит ссылку на заполнитель _T. Все остальные ссылки на идентификатор должны быть известны, когда определяется класс дженерика, а не когда дженерик специализируется. 3.Блок локальных переменных определяется следующим образом: 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; Дженериками могут быть определены не только классы, но и другие типы: {$mode objfpc} {$INTERFACES CORBA} type generic PlanarCoordinate<t> = record x,y : t; end;
TScreenCoordinate = specialize PLanarCoordinate<word>; TDiscreteCoordinate = specialize PlanarCoordinate<integer>; TRealCoordinate = specialize PlanarCoordinate<extended>;
generic TDistanceFunction<t> = function (x,y : t) : Extended of object;
TScreenDistance = specialize TDistanceFunction<word>; TDiscreteDistance = specialize TDistanceFunction<integer>; TRealDistance = specialize TDistanceFunction<Extended>;
generic TArray<t> = array of t;
TMyIntegerArray = specialize TArray<integer>;
generic IList<_T> = Interface Function GetItem(AIndex : Integer) : _T; Procedure SetItem(AIndex : Integer; AValue : _T); Function GetCount : Integer; Property Items [AIndex : Integer] : _T Read GetItem Write SetItem; Property Count : Integer Read GetCount; end;
generic TList<_T>=class(TObject, specialize IList<_T>) public type TCompareFunc = function(const Item1, Item2: _T): Integer; Function GetItem(AIndex : Integer) : _T; Procedure SetItem(AIndex : Integer; AValue : _T); Function GetCount : Integer; Public data : _T; procedure Add(item: _T); procedure Sort(compare: TCompareFunc); end;
generic TPointSet<t> = array of specialize PlanarCoordinate<t>;
TScreenPointSet = specialize TPointSet<word>; TDiscretePointSet = specialize TPointSet<integer>; TRealPointSet = specialize TPointSet<extended>;
|