As it is, I discovered a bug that caused a double free if you call dispose instead of freemem because data should be set to nil after the call to freemem.
I corrected that code, with an example call to the explicit constructor.
{$mode delphi} // or {$mode objfpc}{$modeswitch advancedrecords}
type
pdatao= ^datao;
datao = record
Data: Pointer;
constructor init(size:PtrUint);
Class operator initialize(var rec:datao);
Class operator finalize(var rec:datao);
end;
constructor datao.init(size:ptrUint);
begin
ReAllocMem(Data,size); // realloc, because initialize has already allocated data.
end;
class operator datao.initialize(var rec:datao);
begin
rec.Data := AllocMem(250);
writeln('At initialization 250 bytes allocated for data');
end;
class operator datao.finalize(var rec:datao);
begin
FreeMem(Rec.Data);
Rec.Data := nil; // otherwise double free.
writeln('At finalization data is free''d');
end;
var
d: pdatao;
begin
New(d);
d^.init(400);
dispose(d);
end.
The bug was only using the explicit constructor.
There is still a peculiarity, though:
If you define an explicit constructor, finalize is called twice, harmless but superfluous.
If you change the explicit constructor to a procedure this does not happen.
Maybe PascalDragon can shed some light on it.