So I'm kinda new to OO programming. Delphi has properties which are intended to be a "more elegant" way to acess class data than getters/setters (read it here usage of property vs getters/setters in business classes).
When should I use the fields directly and when should I use getters/setters inside the property? I'm gessing only when the data needs to be manipulated, but I'm not sure.
Edit:
Is it wrong to omit a setter that does nothing but return the value of the field itself?
property Field :integer read FField write FField;
For starters, a quick summary from the documentation on properties:
A property, like a field, defines an attribute of an object. But while a field is merely a storage location whose contents can be examined and changed, a property associates specific actions with reading or modifying its data. Properties provide control over access to an object's attributes, and they allow attributes to be computed.
Separation of storage and access can indeed be achieved by the use of just getters and setters, and leave the property be. That is true, but the question you link to originates from a language difference: Delphi does have properties, and the answers there already explain why to use them. The two most obvious reasons are (1) cleaner code and (2) assignment capability. I think this answer deals with it quite extensive already.
Furthermore, without the use of properties, getters and setters are always needed, where with properties they are not. Assume a setter implementation, but no getter: a property can directly read the field.
When you just declare a property's name and its type, Delphi's class completion defaults to reading a private field and a private setter which sets the private field. Mind that this is just the default configuration, which you again can modify to your needs. When you fully specify the property declaration, class completion will comply and add a private field, a getter and/or setter as required for your declaration.
Is it wrong to omit a setter that does nothing but return the value of the field itself?
When a property has no getter nor setter and it just reads and writes the field, then you could conclude that there is no difference beside being consistent. But that is not the case. The field and the property have distinct names, and therefore possibly distinct meaning. Meaning that you can give. See Using properties instead of fields in class methods of the same unit is a bad practice?.
... I'm gessing only when the data needs to be manipulated ...
Well, that is partly true. Manipulation is one of the many reasons. Consider a Price
property of type String
, and its private field FPrice
:
FPrice
is part of another field, or when it otherwise is beyond the responsibility of this class,Note that a Price
property is quite rudimentary. Leaving its setter or getter for future implementation is very well possible. But imagine more advanced properties which cannot do without setter or getter:
A field that needs to be created before consulting:
function TMyObject.GetBarelyUsed: TRare;
begin
if FBarelyUsed = nil then
FBarelyUsed := TRare.Create(Self);
Result := FBarelyUsed;
end;
An item can be selected, but the item itself does not know what to do. Instead the owner does. Notice the complete absence of the private field in this case:
procedure TItem.SetSelected(Value: Boolean);
begin
if Value <> Selected then
begin
if Value then
Owner.Selection.Add(Self)
else
Owner.Selection.Remove(Self);
end;
end;
An image control, specialized in viewing your own image format. Assignment of the FileName
property involves: checking the correct file extension, checking file existance, storing the file name in the private field, loading the file, adjusting the pictures' dimensions, or else undoing the previous assignment:
procedure TAwDxfImage.SetFileName(const Value: TFileName);
begin
if FFileName <> Value then
if SameText(ExtractFileExt(Value), '.' + SDxf) and
FileExists(Value) then
begin
FFileName := Value;
FGraphic.LoadFromFile(FFileName);
FGraphic.SetBounds(Width, Height);
end
else
begin
FFileName := '';
FGraphic.Clear;
end;
end;
Source: NLDelphi
In addition to @NGLN
answer there is another use case for property getter/setter.
Accessing class instances through interface is only possible via instance methods. If you have to access property in such case you have to implement getter/setter methods.
type
IField = interface
function GetField: integer;
procedure SetField(value: integer);
property Field: integer read GetField write SetField;
end;
TField = class(TInterfacedObject, IField)
protected
FField: integer;
function GetField: integer;
procedure SetField(value: integer);
public
property Field: integer read GetField write SetField;
end;
var
f: IField;
x, n: integer;
...
f := TField.Create;
f.Field := 5;
f.SetField(6);
n := f.Field;
x := f.GetField;
Of course, depending whether you need only read or write access to that property you can omit setter or getter in your interface declaration.
Keep in mind that accessing instance through interface gives all interface implemented methods public visibility. That is why in above example you can call f.GetField
despite it being declared protected (or even private).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With