my issue is pretty simple. I have a dwsUnit which have this code:
type
TPointCoord = record
X: Float;
Y: Float;
Z: Float;
end;
type
TMyClass = class
private
fPosition: TPointCoord;
function GetPosition: TPointCoord;
procedure SetPosition(Val: TPointCoord);
public
property Position: TPointCoord read GetPosition write SetPosition;
constructor Create;
end;
function TMyClass.GetPosition: TPointCoord;
begin
Result := fPosition;
end;
procedure TMyClass.SetPosition(Val: TPointCoord);
begin
fPosition := Val;
end;
constructor TMyClass.Create;
begin
inherited Create;
fPosition.X := 1;
fPosition.Y := 2;
fPosition.Z := 3;
end;
var
mc: TMyClass;
begin
mc := TMyClass.Create;
mc.Position.X := 2; //Syntax Error
end.
At mc.Position.X (or Position.Y or Z) i get:
Syntax Error: Cannot assign a value to the left-side argument [line: 42, column: 17]
What is the meaning of this? Is Record read-only if is a property? And how I can access that from Delphi Side. (the second issue, not a really big deal)
The reason for this error is because you're using a property of type record.
Record type is a value type, which means it's copied on assignment rather than referenced (like a class), so a function (or property) returning a record will make a copy and return a different record.
So your line
mc.Position.X := 2
is effectively equivalent to
temp := mc.getPosition;
temp.X := 2;
with "temp" being a different variable/storage from fPosition, so that code wouldn't change fPosition.X, it would only the "hidden" temporary copy's X field.
As this is generally unlikely to be what you're after, the DWS compiler, just like Delphi, throws an error.
The typical solution is to offer a distinct PositionX property, which will provide access to the X field of fPosition like
property PositionX : TPointCoord read (FPosition.X) write (FPosition.X);
or you can use explicit getters/setters, if you need more than the X field assigned.
Another solution would be use a reference types (a class f.i.), though this may not be very practical for a position or coordinate.
While LHirstov code will work with DWScript that same particular code might not work with some older versions of Delphi.
So for those using older versions of Delphi I recomend simply adding more properties to TmyClass instead of modifying record.
What you need is simply add three new properties (one for each position parameter) and then define their Getter/Setter method to modify these specific parameters individually.
type
TPointCoord = record
X: Float;
Y: Float;
Z: Float;
end;
TMyClass = class
private
fPosition: TPointCoord;
function GetPosition: TPointCoord;
function GetPositionX: Float;
function GetPositionY: Float;
function GetPositionZ: Float;
procedure SetPosition(Val: TPointCoord);
procedure SetPositionX(Val: Float);
procedure SetPositionY(Val: Float);
procedure SetPositionZ(Val: Float);
public
property Position: TPointCoord read GetPosition write SetPosition;
property PositionX: TPointCoord read GetPositionX write SetPositionX;
property PositionY: TPointCoord read GetPositionY write SetPositionY;
property PositionZ: TPointCoord read GetPositionZ write SetPositionZ;
constructor Create;
end;
function TMyClass.GetPosition: TPointCoord;
begin
Result := fPosition;
end;
procedure TMyClass.SetPosition(Val: TPointCoord);
begin
fPosition := Val;
end;
function TMyClass.GetPositionX: Float;
begin
Result := fPosition.X;
end;
procedure TMyClass.SetPositionX(Val: Float);
begin
fPosition.X := Val;
end;
function TMyClass.GetPositionX: Float;
begin
Result := fPosition.Y;
end;
procedure TMyClass.SetPositionY(Val: Float);
begin
fPosition.Y := Val;
end;
function TMyClass.GetPositionX: Float;
begin
Result := fPosition.Z;
end;
procedure TMyClass.SetPositionZ(Val: Float);
begin
fPosition.Z := Val;
end;
So then in the end you access to specific position parameters using:
mc.PositionX := 2;
Now you might be asking yourself do I still need the old Position property. While you technically don't need it it could still come in handy when you need to read or write the position record as a whole.
You have property of type TPointCoord and you want to assign only X coord, that's why you have an error. If you want to deal with X,Y and Z separately then you must assign properties to each of them. Here is an axample for X:
type
TPointCoord = record
private
fX: real;
fY: real;
fZ: real;
function GetX: real;
procedure SetX(value: real);
public
property X: real read GetX write SetX;
end;
function TPointCoord.GetX: real;
begin
Result:=fX;
end;
procedure TPointCoord.SetX(value: Real);
begin
fX:=Value;
end;
With the example above your statement mc.Position.X := 2;
will be OK.
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