Difference between revisions of "Templates"

From Free Pascal wiki
(New page)
 
(Added example code)
Line 6: Line 6:
  
 
Classical example of basic generic class is list of items. Current Free Pascal offer three ways of use lists:
 
Classical example of basic generic class is list of items. Current Free Pascal offer three ways of use lists:
* array of - classical dynamic array structure which can hold dynamic items of same type. Items are accessible by direct addressing SomeArray[Index]. SetLength and Length functions are used to handle size.  
+
* '''array of''' - classical dynamic array structure which can hold dynamic items of same type. Items are accessible by direct addressing SomeArray[Index]. SetLength and Length functions are used to handle size.  
* TList - objective way where class handle all list operations. Implementation in LCL keep compatibility with VCL where TList holds list of Pointers. If list of different item type is desired complete new class have to be copied and rewrited or typecasting have to be used in every place where list item is referenced. Typecasting is not effective e.g. Pointer(Byte) and not type safe Pointer(Int64). TList index is of type Integer. If Int64 or SmallInt index is needed than class have to be copied and rewrited.
+
* '''TList''' - objective way where class handle all list operations. Implementation in LCL keep compatibility with VCL where TList holds list of Pointers. If list of different item type is desired complete new class have to be copied and rewritten or typecasting have to be used in every place where list item is referenced. Typecasting is not effective e.g. Pointer(Byte) and not type safe Pointer(Int64). TList index is of type Integer. If Int64 or SmallInt index is needed than class have to be copied and rewritten.
* TCollection - is more generic and type safe but heavier solution for storing list of items. In this approach programmer have to create item class which inherits from TCollectionItem and set this newly created class type to TCollection constructor parameter.
+
* '''TCollection''' - is more generic and type safe but heavier solution for storing list of items. In this approach programmer have to create item class which inherits from TCollectionItem and set this newly created class type to TCollection constructor parameter.
  
===Inheritance==
+
Templates tries to solve problem using concept of parametrized templates. Generic unit is written only once as template with use of generic not specified types in both interface and implementation section. Than in process of specialization class template is used and general template parameters are replaced by specific types. In result new specialized class is created.
 +
 
 +
''GenericListInterface.tpl:''
 +
<delphi>  // TGList<T> = class
 +
  TGList = class
 +
    Items: array of T;
 +
    procedure Add(Item: T);
 +
  end;</delphi>
 +
 
 +
''GenericListImplementation.tpl:''
 +
<delphi>procedure TGList.Add(Item: T);
 +
begin
 +
  SetLength(Items, Length(Items) + 1); 
 +
  Items[Length(Items) - 1] := Item;
 +
end;</delphi>
 +
 
 +
In process of specialization early created template files are included to new unit.
 +
 
 +
''ListInteger.pas:''
 +
<delphi>unit ListInteger;
 +
 
 +
interface
 +
 
 +
uses
 +
  Classes;
 +
 
 +
type
 +
  T = Integer; // T is specified to some exact type
 +
{$INCLUDE 'GenericListInterface.tpl'}
 +
 
 +
type
 +
  TListInteger = class(TGList)
 +
    // Additional fields and methods can be added here
 +
  end;
 +
 
 +
implementation
 +
 
 +
{$INCLUDE 'GenericListImplementation.tpl'}
 +
 
 +
end.</delphi>
 +
 
 +
Finally we have new specialized unit called ListInteger and we can use our new specialized type in some code.
 +
 
 +
<delphi>program GenericTest;
 +
uses
 +
  ListInteger;
 +
var
 +
  List: TListInteger;
 +
begin
 +
  try
 +
    List := TListInteger.Create;
 +
    List.Add(1);
 +
    List.Add(2);
 +
    List.Add(3);
 +
  finally
 +
    List.Free;
 +
  end;
 +
end.</delphi>
 +
 
 +
===Inheritance===
 +
 
 +
===Constrains===
  
 
==Example units==
 
==Example units==

Revision as of 10:25, 29 October 2010

Introduction

Templates is simple mechanism to solve problem of writing duplicate code to implement general class for specific type in strong typed language. It is used mainly for base non-object types as in case of objects inheritance of single base class TObject can be used to build general classes. In advanced languages templates are replaced by native language implementation called generics. Native implementation of generics in FPC 2.4.0 is not complete neither practically usable yet. Then templates could be used temporary in the meantime.

Usage

Classical example of basic generic class is list of items. Current Free Pascal offer three ways of use lists:

  • array of - classical dynamic array structure which can hold dynamic items of same type. Items are accessible by direct addressing SomeArray[Index]. SetLength and Length functions are used to handle size.
  • TList - objective way where class handle all list operations. Implementation in LCL keep compatibility with VCL where TList holds list of Pointers. If list of different item type is desired complete new class have to be copied and rewritten or typecasting have to be used in every place where list item is referenced. Typecasting is not effective e.g. Pointer(Byte) and not type safe Pointer(Int64). TList index is of type Integer. If Int64 or SmallInt index is needed than class have to be copied and rewritten.
  • TCollection - is more generic and type safe but heavier solution for storing list of items. In this approach programmer have to create item class which inherits from TCollectionItem and set this newly created class type to TCollection constructor parameter.

Templates tries to solve problem using concept of parametrized templates. Generic unit is written only once as template with use of generic not specified types in both interface and implementation section. Than in process of specialization class template is used and general template parameters are replaced by specific types. In result new specialized class is created.

GenericListInterface.tpl: <delphi> // TGList<T> = class

 TGList = class
   Items: array of T;
   procedure Add(Item: T);
 end;</delphi>

GenericListImplementation.tpl: <delphi>procedure TGList.Add(Item: T); begin

 SetLength(Items, Length(Items) + 1);  
 Items[Length(Items) - 1] := Item;

end;</delphi>

In process of specialization early created template files are included to new unit.

ListInteger.pas: <delphi>unit ListInteger;

interface

uses

 Classes;

type

 T = Integer; // T is specified to some exact type

{$INCLUDE 'GenericListInterface.tpl'}

type

 TListInteger = class(TGList)
   // Additional fields and methods can be added here
 end;

implementation

{$INCLUDE 'GenericListImplementation.tpl'}

end.</delphi>

Finally we have new specialized unit called ListInteger and we can use our new specialized type in some code.

<delphi>program GenericTest; uses

 ListInteger;

var

 List: TListInteger;

begin

 try
   List := TListInteger.Create;
   List.Add(1);
   List.Add(2);
   List.Add(3);
 finally
   List.Free;
 end;

end.</delphi>

Inheritance

Constrains

Example units

See also

External links