The "my" is an object instance of some class, defined as "var my : TMySimpleObject", that could have been declared as:
if Assigned(my) then Caption := my.StringValue else Caption := '"my" not assigned';
The TMySimpleObject class defines a string property called "StringValue" using a private fStringValue field to write and/or read the value of the StringValue property.
type TMySimpleObject = class private fStringValue: string; public property StringValue : string read fStringValue write fStringValue; end;
If "my" object, in the example above, is not assigned and you try to access (read) its StringValue property, you will receive an Access Violation.
From my point of view, sometimes it takes to much time (lines of code) to always check if the object is assigned or not, to read its properties, and not receive access violations.
How aout simply reading my.StringValue, without the need to check if the object is nil?
Property Getters to the RescueWith the next declaration, using property getter method, you do not need to care if an object is nil, or better to say, you would test for nil in the getter of the property:
With the above implementation of the StringProp property, you are safe to read the value of the property even when the instance of the TMyObject class is nil (not assigned):
type TMyObject = class(TMySimpleObject) private fStringProp : string; function GetStringProp: string; public property StringProp : string read GetStringProp; end; .... function TMyObject.GetStringProp: string; begin if Assigned(Self) then result := fStringProp else result := 'my object is nil'; end;
No need for:
Caption := my.StringProp
Note that the getter method, GetStringProp, checks if the instance is assigned. If "Self" is not assignend, a default value is returned - in the above example: "my object is nil".
if Assigned(my) then Caption := my.StringProp else Caption := '"my" not assigned';
Using a getter method you can save lines of code - check if the instance is assigned in the property getter and not where you actually need the value of the property!
If Self = nil, simply return something that for you is a "default value" for non instantiated instances of a class.
Such a trick could not be used to write values to properties - as obviously for writing you need a class instance that is not nil.
In my applications I do have various classes that only expose read only properties, where their vaues are set using an overriden construtor.
What If You Need to Access Properties That Are Objects?Here's a more complex example:
The TMyObjectEx extends TMyObject by including an object type property, using a sub class named "TMySubObject".
type TMyObjectEx = class(TMyObject) private type TMySubObject = class private fMySubIntValue : integer; function GetMySubIntValue: integer; public property MySubIntValue : integer read GetMySubIntValue; end; private fSubObject: TMySubObject; function GetSubObject: TMySubObject; public destructor Destroy; override; property SubObject : TMySubObject read GetSubObject; end;
Again, we want to be able to read the MySubIntValue property value (integer). The MySubIntValue is a property of TMySubObject which is exposed as a read only property of the TMyObjectEx class.
Here's the implementation of the GetMySubIntValue getter:
With the above declaration, you can ask for the value of "my.SubObject.MySubIntValue" even if "my" is NIL!
function TMyObjectEx.TMySubObject.GetMySubIntValue: integer; begin if Assigned(Self) then result := fMySubIntValue else result := -1; //default value for non assigned objects end; function TMyObjectEx.GetSubObject: TMySubObject; begin if Assigned(Self) then begin if fSubObject = nil then fSubObject := TMyObjectEx.TMySubObject.Create; result := fSubObject; end else result := nil; end; destructor TMyObjectEx.Destroy; begin FreeAndNil(fSubObject); inherited; end;
Therefore, the next line will not raise an access violation EVEN if "my" is NIL!
Im not sure if it is "OOP-OK" to use the presented way of reading properties for non assigned objects - but I do use it and I'm happy not to always need to check if some object is assigned or not.
Caption := my.StringProp + IntToStr(my.SubObject.MySubIntValue);
Of course, in some scenarioos you MUST check if an object is nil, but for some, the above idea would come handy :)