[fpc-pascal] Read-only global references

Marcos Douglas md at delfire.net
Sun Mar 6 00:15:51 CET 2011


On Sat, Mar 5, 2011 at 7:05 PM, Mark Morgan Lloyd
<markMLl.fpc-pascal at telemetry.co.uk> wrote:
> Marcos Douglas wrote:
>>
>> On Sat, Mar 5, 2011 at 8:24 AM, Mark Morgan Lloyd
>> <markMLl.fpc-pascal at telemetry.co.uk> wrote:
>>>
>>> Where a unit exports an instance of an object, what's best practice for
>>> making this read-only? I'm referring to the object reference itself here,
>>> not properties of the object.
>>>
>>> Where I've done this in the past I've used a function:
>>>
>>> interface
>>>
>>> function InitText: TFormattedString;
>>>
>>> implementation
>>>
>>> var     xInitText: TFormattedString= nil;
>>>
>>> function InitText: TFormattedString;
>>>
>>> begin
>>>  result := xInitText
>>> end { InitText } ;
>>>
>>> Is there a better way using e.g. global properties that doesn't
>>> necessitate
>>> both a property and an explicit function?
>>>
>>> property InitText: TFormattedString read xInitText;
>>>
>>> The obvious problem here is that xInitText is a forward reference to an
>>> unexported variable.
>>
>> Make a function to return a global variable does not make it read only.
>> If I use your function like this:
>> o := InitText;
>> o := nil;  //this is the same xInitText = nil
>
> Disagree. You are changing the value of o, not of xInitText. xInitText is
> initialised once somewhere in the unit exporting it, subsequently its
> properties etc. can be used elsewhere e.g. InitText.AppendFormatted(...).

You right... but not TOTALY.
I made a little program to explain that, but now I'm confusing, see:

program ref;

{$mode objfpc}{$H+}

uses
  sysutils;

type
  TObj = class
  public
    i: integer;
  end;

var
  o1: TObj = nil;
  o2: TObj = nil;

function getobj: TObj;
begin
  if not Assigned(o1) then
    o1 := TObj.Create;
  o1.i := 1;
  result := o1;
end;

begin
  o1 := getobj;
  o2 := o1;
  writeln('o1.i: ', o1.i);
  writeln('o2.i: ', o2.i);
  writeln('o2.i change to 2');
  o2.i := 2;
  writeln('o1.i = 2 too?": ', o1.i = 2);
  writeln('Destroy o2');
  o2.Free;
  writeln('o1.i still exists?: ', Assigned(o1), ' so, write o1.i: ', o1.i);
  writeln('o1.i change to 3');
  o1.i := 3;
  writeln('o1.i: ', o1.i);
  try
    o1.Free;
  except
    on e: Exception do
      writeln(e.Message);
  end;
  readln;
end.

The o1 variable still exists, even after o2 was destroed! But o2 point to o1...
The variable o1 exists, but I can't destroy it! Why??

I test on Lazarus and Delphi 7.
The only diference is in this line:
  writeln('o1.i still exists?: ', Assigned(o1), ' so, write o1.i: ', o1.i);

In Lazarus, the result is:
TRUE | 0

In Delphi, the result is:
TRUE | 2

Again... Why??


Marcos Douglas



More information about the fpc-pascal mailing list