[fpc-pascal] Read-only global references
Marcos Douglas
md at delfire.net
Sun Mar 6 01:57:41 CET 2011
On Sat, Mar 5, 2011 at 8:15 PM, Marcos Douglas <md at delfire.net> wrote:
> 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??
This occurs because I use the "pointer of memory" of property "i" and
the compiler ignore the instance of object?
I don't understand... if o1==o2 and o1 was released (Free and Nil),
why I can continue using o2 if it points to the same memory, i.e., o1?
And why I can't destroy it?
I think the property "i" continue existing and, because that, I can
continue using "i" property through o2 variable. Is that right?
Marcos Douglas
More information about the fpc-pascal
mailing list