Branko Sretenovic
Branko Sretenovic

Reputation: 23

Delphi Class Destructor

I don't understand how a class destructor works! I read grammar semantics and syntax for a class destructor, but I haven't found many complete code examples.

I tried to create a simple code (see below), and that code eventually displays Start, but it does not display Finish.

Can you help me find a way how to display Finish by changing the code below within Project1.dpr and Unit1.pas?

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Unit1 in 'Unit1.pas';

begin
  Race:= TRace.Create;
  Race.Destroy;
  Readln
end.
unit Unit1;

interface

type
  TRace= class
    class constructor Start;
    class destructor Finish;
  end;

var
  Race: TRace;

implementation

class constructor TRace.Start;
begin
  Writeln('Start')
end;

class destructor TRace.Finish;
begin
 Writeln('Finish')
end;

end.

I use Delphi Sydney 10.4 Community Edition. Thx

Upvotes: 2

Views: 2966

Answers (2)

Rob Lambden
Rob Lambden

Reputation: 2293

The class destructor will run when the class itself (not an instance of the class) is disposed of, not for any individual object. The class constructor will run when the class itself is created.

What that means is that when the class is loaded (during the initialization of the executable or package that the class code is in) the class constructor is run, and when the class is unloaded (or disposed of) (during finalization) the class destructor is run.

The class is a TClass, whereas instances of that class are descendants of TObject (TRace in your example). So if you create a TRace it does not call the class constructor for TRace, similarly if you dispose of a TRace it does not call the class destructor for TRace.

The documentation which @RemyLebeau linked to in his comments makes it clear that these methods are 'not available to developers' - you don't ever call them, the system does.

To get what you want you just need an ordinary instance destructor as shown:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}
type
  TRace= class(TObject)
  public
    constructor Create;    // by convention we use Create
    destructor Destroy; override;
  end;

constructor TRace.Create;
begin
  Writeln('Start');
  inherited Create();
end;

destructor TRace.Destroy;
begin
  Writeln('Finish');
  inherited;
end;

var
  Race: TRace;

begin
  Race:= TRace.Create;
  Race.Free;
  Readln;
end.

Using a class constructor and / or a class destructor is an unusual requirement. It could be used to initialise static resources that are needed for the class to operate, but from code that I have seen it is more usual for this to be done in the initialization and finalization sections.

In Delphi class methods are called with Self referring to the class (a TClass) and not to an instance of the class and so they cannot access any instance data, but can still access any static data.

Upvotes: 3

Branko Sretenovic
Branko Sretenovic

Reputation: 23

David's comment is correct. I have added Readln below Writeln('Finish') and it worked.

It's because finalization is the place where class destructor places its commands in, and finalization comes very last.

Upvotes: 0

Related Questions