procedure SetType (var SomeObject; VMT: PObjectType);
The procedure SetType
explicitly assigns a value to the
implicit VMT field of an object. This is normally done implicitly
when a constructor is called.
You can use this to write a polymorphic I/O routine which reads an
object from a file. In this case, you cannot reasonably use
New
to allocate the storage, but you GetMem
it and
initialize the object manually using SetType
before calling
the constructor explicitly.
The only values you should assign to an object via SetType
are actual VMT pointers that were obtained via TypeOf
. In
particular, declaring a record like the one shown in the description
of PObjectType
and assigning a pointer to it to an object via
SetType
will usually not work because the virtual method
pointers are missing.
Since SetType
is a dangerous feature, it yields a warning
unless {$X+}
is given.
SetType
is a GNU Pascal extension.
program SetTypeDemo; type BasePtr = ^BaseObj; BaseObj = object constructor Load; end; ChildObj = object (BaseObj) constructor Load; end; constructor BaseObj.Load; begin end; constructor ChildObj.Load; begin end; {$X+} { This is somewhat fragmentary code. } function GetObject (var InputFile: File) = Result: BasePtr; const VMTTable: array [1 .. 2] of PObjectType = (TypeOf (BaseObj), TypeOf (ChildObj)); var Size: Cardinal; TypeID: Integer; VMT: PObjectType; begin { Read the size of the object from some file and store it in `Size'. } BlockRead (InputFile, Size, SizeOf (Size)); { Allocate memory for the object. } GetMem (Result, Size); { Read some ID from some file. } BlockRead (InputFile, TypeID, SizeOf (TypeID)); { Look up the `VMT' from some table. } { Range checking wouldn't be a bad idea here ... } VMT := VMTTable[TypeID]; SetType (Result^, VMT); { Now the object is ready, and the constructor can be called. } { Look up the correct constructor from some table and call it. } end; begin end.