Metaclasses

A metaclass (or class reference) is a type that refers to a class itself, rather than an instance of a class. This allows for powerful dynamic instantiation patterns and reflective programming.

Syntax

Metaclasses are declared using the class of syntax.

type
  TBase = class
    constructor Create; virtual; begin end;
  end;
type
  TDerived = class(TBase)
    constructor Create; override; begin end;
  end;
type
  TBaseClass = class of TBase;

Dynamic Instantiation

The primary use of metaclasses is to create objects when the exact class is only known at runtime.

type
  TBase = class
    constructor Create; virtual; begin end;
  end;
type
  TDerived = class(TBase)
    constructor Create; override; begin end;
  end;
type
  TBaseClass = class of TBase;

var cls: TBaseClass := TDerived;
var obj := cls.Create;
PrintLn(obj.ClassName);
Result
TDerived

Virtual Constructors

For polymorphic instantiation to work correctly, the constructor must be declared as virtual in the base class and override in the subclasses. If you call a non-virtual constructor on a metaclass, the base class constructor will be called regardless of the class the metaclass variable currently holds.

Class Methods and Properties

Metaclasses can be used to call class methods and access static properties.

type
  TUtility = class
    class procedure DoSomething;
    begin
       PrintLn('Doing something...');
    end;
  end;
type
  TUtilityClass = class of TUtility;

var v: TUtilityClass := TUtility;
v.DoSomething;
Result
Doing something...

Type Checking and Casting

The is and as operators are used to check and cast object instances.

type
  TBase = class
    constructor Create; virtual; begin end;
  end;
type
  TDerived = class(TBase)
    constructor Create; override; begin end;
  end;
type
  TBaseClass = class of TBase;

var obj: TObject := TDerived.Create;
if obj is TBase then
  PrintLn('obj is a TBase');
var cls: TBaseClass := TDerived;
if obj is cls then
  PrintLn('obj is an instance of ' + cls.ClassName);
var d := obj as TDerived;
PrintLn(d.ClassName);
Result
obj is a TBase
obj is an instance of TDerived
TDerived

TClass and ClassType

Every object has a ClassType property that returns its metaclass. TClass is the base metaclass for all classes.

type
  TDerived = class
  end;

var obj: TObject := TDerived.Create;
var anyClass: TClass := obj.ClassType;
PrintLn(anyClass.ClassName);
Result
TDerived
On this page