I've been scratching my head for the last few hours since a field was being overwritten when I didn't expect it. I think I've worked out what was going on, but still feel it worth raising for discussion. FPC 3.2.2, other versions untested.
program testSL;
{$mode ObjFPC}{$H+}
uses
Classes;
type
String31= string[31];
TVertexDegs= record
lat, lon: double
end;
(* This is primarily a container for binary values extracted from an ADS-B block,
but might also be used in a couple more roles relating to caching etc. In most
cases it is attached to the Objects[0] of the TFlight (in effect a TStringList)
containing the original (i.e. text-format) data.
*)
TTicket= class
class var InfieldDegs: TVertexDegs; (* Used for range calculation *)
class var RadioDegs: TVertexDegs; (* Used for slant calculation *)
Timestamp: TDateTime;
IcaoAddress: string31;
constructor Create(now: TDateTime);
(* Return a newly-created TTicket filled in from this one.
*)
function Duplicate(): TTicket;
end;
constructor TTicket.Create(now: TDateTime);
begin
inherited Create;
Timestamp := now;
self.IcaoAddress := '<none>'
end { TTicket.Create } ;
(* Return a newly-created TTicket filled in from this one.
*)
function TTicket.Duplicate(): TTicket;
var
original: TTicket;
scratch: string31;
begin
original := self;
scratch := original.IcaoAddress;
scratch := original.IcaoAddress;
// At this point, the field is still as expected so has not been overwritten by
// the action of reading it.
result := TTicket.Create(0.0 { self.Timestamp});
scratch := original.IcaoAddress;
// The field has now been overwritten to the value in Create().
end { TTicket.Duplicate } ;
var
t1, t2: TTicket;
begin
t1 := TTicket.Create(0.0 { Now() } );
t1.IcaoAddress := 'Initialised';
WriteLn(t1.IcaoAddress);
t2 := t1.Duplicate;
WriteLn(t1.IcaoAddress)
end.
With the code as above, my output is
$ ./testSL
Initialised
<none>
i.e. the IcaoAddress field is being overwritten when I go to create a new instance.
What's actually happening is that the class modifier is running forward. If I insert an explicit public like this
TTicket= class
class var InfieldDegs: TVertexDegs; (* Used for range calculation *)
class var RadioDegs: TVertexDegs; (* Used for slant calculation *)
public
Timestamp: TDateTime;
IcaoAddress: string31;
...
then behaviour is as expected.
As far as I can see, the manual doesn't describe class as a visibility modifier, so while I think I now see /what/ is happening I'm a little nonplussed as to /why/.
Comments would be appreciated.
MarkMLl