Compiler Directives Delphi

Function|Procedure declaration; Dynamic;


Description
The Dynamic directive allows a class method to be override (replaced) by a same named method in a derived class.

You would mark a function or procedure as Dynamic when you happily allow a programmer who creates a class based on your class to replace its functionality.

For example, you might allow a base class to paint a canvas in white, but allow a derived class to paint a picture on the canvas instead. Here, the Dynamic directive is allowing the code to be extended, to be enriched.

Dynamic may be followed by the Abstract directive. This modifies the effect of the Dynamic directive. It means that the current class must not code the method - it is there only as a placeholder to remind and ensure that derived classes implement it.

Notes
Dynamic is semantically equivalent to Virtual. The former is optimised for memory, the latter for speed.


Related commands
Abstract Defines a class method only implemented in subclasses
Class Starts the declaration of a type of object class
Function Defines a subroutine that returns a value
Procedure Defines a subroutine that does not return a value
Overload Allows 2 or more routines to have the same name
Override Defines a method that replaces a virtual parent class method
Virtual Allows a class method to be overriden in derived classes

Example code : Implementing abstract dynamic class methods
// Full Unit code.
// -----------------------------------------------------------
// You must store this code in a unit called Unit1 with a form
// called Form1 that has an OnCreate event called FormCreate.
unit Unit1;
interface
uses
Forms, Dialogs, Classes, Controls, StdCtrls, SysUtils;
type
// Define a base TPolygon class :
// This class is a traingle if 3 sides, square if 4 sides ...
TPolygon = class
private
sideCount : Integer; // How many sides?
sideLength : Integer; // How long each side?
shapeArea : Double; // Area of the polygon
protected
procedure setArea; Dynamic; Abstract; // Must be implemented in child
property count : Integer read sideCount;
property length : Integer read sideLength;
property area : Double read shapeArea;
constructor Create(sides, length : Integer);
end;
// Define triangle and square descendents
TTriangle = class(TPolygon)
protected
procedure setArea; override; // Override the abstract method
end;
TSquare = class(TPolygon)
protected
procedure setArea; override; // Override the abstract method
end;
// Define the form class used by this unit
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm} // Include form definitions
// Create the TPolygon object
constructor TPolygon.Create(sides, length : Integer);
begin
// Save the number and length of the sides
sideCount := sides;
sideLength := length;
// Set the area using the abstract setArea method :
// This call will be satisfied only by a subclass
setArea;
end;
// Implement the abstract setArea parent method for the triangle
procedure TTriangle.setArea;
begin
// Calculate and save the area of the square
shapeArea := (sideLength * sideLength) / 2;
end;
// Implement the abstract setArea parent method for the square
procedure TSquare.setArea;
begin
// Calculate and save the area of the square
shapeArea := sideLength * sideLength;
end;
// Main line code
procedure TForm1.FormCreate(Sender: TObject);
var
triangle : TTriangle;
square : TSquare;
begin
// Create a triangle and a square
triangle := TTriangle.Create(3, 10);
square := TSquare.Create(4, 10);
// Show the areas of our polygons:
ShowMessageFmt('Triangle area = %f',[triangle.area]);
ShowMessageFmt('Square area = %f',[square.area]);
end;
end.

Triangle area = 50.0
Square area = 100.0