Record helper, Felder verbergen, auf verborgene Felder zugreifen?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Bitschubser
Beiträge: 62
Registriert: Mo 27. Aug 2012, 15:43

Record helper, Felder verbergen, auf verborgene Felder zugreifen?

Beitrag von Bitschubser »

Hallo zusammen,

nach längerer Abwesenherit gleich eine moderne Frage:

Bei ADVANCEDRECORDS ist es ja kein Problem Record-Felder zu verbergen:

in irgendeiner Unit die man nicht ändern kann/darf/will:

Code: Alles auswählen

type
  TOriginalRecord = record
    FeldA : longint;
    FeldB : longint;
    FeldC : string;
  end;             
im neuen Code:

Code: Alles auswählen

  RecordHelperA = record helper for TOriginalRecord
    function Test : longint;
    function FeldC : string;
  end;
[...]

Code: Alles auswählen

function RecordHelperA.Test : longint;
begin
  Result := FeldA;
end;

function RecordHelperA.FeldC : string;
begin
  Result := '123';
end;             
Wenn man auf das verborgene Feld trotzdem zugreifen will funktioniert das hier allerdings (erwartungsgemäß) nicht (Endlosschleife):

Code: Alles auswählen

function RecordHelperA.FeldC : string;
begin
  Result := FeldC + '123';
end;          


Wären advanced records oop würde ich auf den Vorgänger-Typ casten oder sowas wie "inherited self." verwenden, geht hier natürlich nicht.

Lässt sich das Problem trotzdem mit advanced records lösen?

Gruß, Ingo

Warf
Beiträge: 2141
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Record helper, Felder verbergen, auf verborgene Felder zugreifen?

Beitrag von Warf »

Benutz ein Private Field:

Code: Alles auswählen

{$ModeSwitch advancedrecords}

type
  TTest = record
    A, B: Integer;
  end;

  TTestWrapper = record
  private
    internal: TTest;
    function GetB: Integer;
    procedure SetB(AValue: Integer);
  public
    property A: Integer read internal.A write internal.A; // Direkter Zugriff auf A
    property B: Integer read GetB write SetB; // Getter und Setter auf B
  end;

function TTestWrapper.GetB: Integer;
begin
  Result := Internal.B + 42;
end;

procedure TTestWrapper.SetB(AValue: Integer);
begin
  Internal.B := AValue - 42;
end;
Wobei für das was du vorhast vermutlich das der bessere weg ist:

Code: Alles auswählen

{$mode objfpc}{$H+}
{$ModeSwitch advancedrecords}
{$ModeSwitch typehelpers}

type
  TTest = record
    A, B: Integer;
  end;

  PTestWrapper = ^TTestWrapper;
  TTestWrapper = record
    internal: TTest;
    property B: Integer read internal.B write Internal.B;
  end;

type

  TTestHelper = type helper for TTest
    function B: Integer;
  end;

function TTestHelper.B: Integer;
begin
  Result := PTestWrapper(@self)^.B + 42;
end;


var
  t: TTest;
begin
  PTestWrapper(@t)^.B := 0; // Direkter zugriff über den Wrapper
  WriteLn(t.B); // Geht über den TestHelper

Antworten