5

私の問題は非常に単純です。私はこのコードを持つ dwsUnit を持っています:

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.

mc.Position.X (または Position.Y または Z) で次を取得します。

Syntax Error: Cannot assign a value to the left-side argument [line: 42, column: 17]

これはどういう意味ですか?がプロパティの場合、レコードは読み取り専用ですか? そして、Delphi 側からアクセスする方法。(2番目の問題、それほど大したことではありません)

4

3 に答える 3

2

このエラーの理由は、レコード タイプのプロパティを使用しているためです。

レコード型は値型です。つまり、(クラスのように) 参照されるのではなく、割り当て時にコピーされるため、レコードを返す関数 (またはプロパティ) はコピーを作成し、別のレコードを返します。

だからあなたのライン

mc.Position.X := 2

実質的に同等です

temp := mc.getPosition;
temp.X := 2;

「temp」は fPosition とは異なる変数/ストレージであるため、コードは fPosition.X を変更せず、「隠された」一時コピーの X フィールドのみを変更します。

一般に、これが求めているものである可能性は低いため、DWS コンパイラは、Delphi と同様にエラーをスローします。

典型的な解決策は、fPosition の X フィールドへのアクセスを提供する個別の PositionX プロパティを提供することです。

property PositionX : TPointCoord read (FPosition.X) write (FPosition.X);

または、X フィールド以上を割り当てる必要がある場合は、明示的なゲッター/セッターを使用できます。

別の解決策は参照型 (クラス fi) を使用することですが、これは位置や座標にはあまり実用的ではないかもしれません。

于 2014-08-12T10:04:35.257 に答える
2

LHirstov コードは DWScript で動作しますが、同じ特定のコードが古いバージョンの Delphi では動作しない可能性があります。

そのため、古いバージョンの Delphi を使用している場合は、レコードを変更する代わりに、TmyClass にプロパティを追加することをお勧めします。

必要なのは、3 つの新しいプロパティ (位置パラメーターごとに 1 つ) を追加し、それらの Getter/Setter メソッドを定義して、これらの特定のパラメーターを個別に変更するだけです。

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;

したがって、最終的には、次を使用して特定の位置パラメーターにアクセスします。

mc.PositionX := 2;

ここで、古い Position プロパティがまだ必要かどうか自問しているかもしれません。技術的には必要ありませんが、ポジション レコード全体を読み書きする必要がある場合に便利です。

于 2014-08-12T06:53:36.937 に答える