Neat. My head spinning, with inner records and nested types, a lot of info. Thank you again. This auto initialization was on my mind, never knew which question to ask, and here it is.
Although my previous example is syntactically correct, you do not need to use fully qualified names. Here is a cleaned up version that may be easier to understand:
{$mode objfpc}{$modeswitch advancedrecords}{$warn 5090 off}
type
TMyObject = object
type
TInnerRecord = record
a,b:integer;
class operator Initialize(var value:TInnerRecord);
end;
strict private
InnerRecord:TInnerRecord;
public
property a:integer read InnerRecord.a write InnerRecord.a;
property b:integer read InnerRecord.b write InnerRecord.b;
end;
class operator TMyObject.TInnerRecord.Initialize(var value:TInnerRecord);
begin
value.a :=100;
value.b :=200;
end;
var
O:TmyObject;
begin
writeln(O.a);
writeln(O.b);
end.
Basically what we do here is move all or any object fields into a local record. This has no effect on performance. These fields can - if necessary - subsequently be initialized through the management operator. I designed it such that the record itself need not be exposed to the outer world, just like you would usually do with normal fields.
The main difference between a constructor and the managed record is that the constructor would be called on a pointer to object, or need to be called manually whereas the management operator is automatically called on the object variable itself.
something like :
var PO:PMyObject;
begin
PO :=New(PMyObject, Init);// contructor
...
Dispose(PO,Done);// destructor
// or
O:TMyObject;
begin
O.Init;// needs to be called manually
With the record, we can also use the finalize management operator instead of a destructor.
It is not just syntactic sugar: this makes your code safer since you do not have to remember to call the constructor and/or destructor for the object. (That is, except if the object is created with New(), In that case you would still need to call Dispose()... )