RAD Studio (Common)
ContentsIndex
PreviousUpNext
Overview of Generics

Delphi supports the use of generics.

The terms generics or generic types describe the set of things in a platform that can be parameterized by type. Generics can refer to generic types and generic methods, i.e., generic procedures and generic functions.  

Generics are a set of abstraction tools that permit the decoupling of an algorithm (such as a procedure or function) or a data structure (such as a class, interface or record) from one or more concrete types that the algorithm or data structure uses. 

A method or data type that uses other types in its definition can be made more general by substituting one or more concrete types with type parameters. Then you add those type parameters to a type parameter list in the method or data structure declaration. This is similar to the way that you can make a procedure more general by substituting instances of a literal constant in its body with a parameter name and adding the parameter to the parameter list of the procedure. 

For example, a class (TMyList) that maintains a list of objects (of type TObject) can be made more reusable and type-safe by substituting uses of TObject with a type parameter name (such as 'T'), and adding the type parameter to the class's type parameter list so that it becomes TMyList<T>. 

Concrete uses (instantiations) of a generic type or method can be made by supplying type arguments to the generic type or method at the point of use. The act of supplying type arguments effectively constructs a new type or method by substituting instances of the type parameter in the generic definition with the corresponding type argument.  

For example, the list might be used as TMyList<Double>. This creates a new type, TMyList<Double>, whose definition is identical to TMyList<T> except that all instances of 'T' in the definition are replaced with 'Double'. 

It should be noted that generics as an abstraction mechanism duplicates much of the functionality of polymorphism, but with different characteristics. Since a new type or method is constructed at instantiation time, you can find type errors sooner, at compile time rather than run time. This also increases the scope for optimization, but with a trade-off - each instantiation increases the memory usage of the final running application, possibly resulting in lower performance.

For example, TSIPair is a class holding two data types, String and Integer:

type
      TSIPair = class
      private
      FKey: String;
      FValue: Integer;
      public
      function GetKey: String;
      procedure SetKey(Key: String);
      function GetValue: Integer;
      procedure SetValue(Value: Integer);
      property Key: TKey read GetKey write SetKey;
      property Value: TValue read GetValue write SetValue;
      end;

To make a class independent of data type, replace the data type with a type parameter.

type
      TPair<TKey,TValue>= class   // declares TPair type with two type parameters
      
      private
      FKey: TKey;
      FValue: TValue;
      public
      function GetKey: TKey;
      procedure SetKey(Key: TKey);
      function GetValue: TValue;
      procedure SetValue(Value: TValue);
      property Key: TKey read GetKey write SetKey;
      property Value: TValue read GetValue write SetValue;
      end;
      
      type
      TSIPair = TPair<String,Integer>; // declares instantiated type
      TSSPair = TPair<String,String>;  // declares with other data types
      TISPair = TPair<Integer,String>;
      TIIPair = TPair<Integer,Integer>;
      TSXPair = TPair<String,TXMLNode>;

Generics are supported by the Delphi for Win32 compiler.

Runtime type identification (RTTI)

In Win32, generics and methods do not have RTTI, but instantiated types do have RTTI. An instantiated type is the combination of a generic with a set of parameters.

Interface GUID

In Win32, an instantiated interface type does not have an interface GUID.

Parameterized method in interface

A parameterized method (method declared with type parameters) cannot be declared in an interface.

Instantiation timing

Instantiation is processed by the compiler. All instantiated objects are emitted into .obj files.

Dynamic instantiation

Dynamic instantiation at runtime is not supported.

Interface constraints

The Win32 interface is not a "light" interface. This means all type parameters with interface constraints always support the COM IUnknown methods _AddRef, _Release and QueryInterface or inherit from TInterfacedObject. Record types cannot specify an interface constraint parameter.

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!