Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Ein Record als Property in einer Klasse (https://www.delphipraxis.net/14594-ein-record-als-property-einer-klasse.html)

Jelly 12. Jan 2004 08:50


Ein Record als Property in einer Klasse
 
Hallo zusammen,

hab ein skurieles Problem. Folgender Code:

Delphi-Quellcode:
type
  TVector = record
               x, y, z : double ;
            end ;

  TProbe = class
  private
    Fr0: TVector;
    Fr1: TVector;
    procedure Setr0(const Value: TVector);
    procedure Setr1(const Value: TVector);
  public
    property r0 : TVector read Fr0 write Setr0 ;
    property r1 : TVector read Fr1 write Setr1 ;
    constructor Create ;
  end ;

var
 Probe : TProbe ;
Probier ich jetzt mittels
Delphi-Quellcode:
Probe.r0.x := 3 ;
einen Wert zuzuweisen, krieg ich ne Fehlermeldung beim Kompilieren:
Zitat:

Zitat von Delphi Compiler
Left side cannot be assigned to

Woran kann das liegen. Lesender Zugriff funktioniert hingegen. Kann man keine Records als Eigenschaften deklarieren etwa?

Wer weiß da Rat?

Gruß,
Tom

Leuselator 12. Jan 2004 08:55

Re: Ein Record als Property in einer Klasse
 
Das ist der Sinn von Properties: die Objektdaten vor direktem Zugriff von aussen zu schützen! Du müßtest schon einen kompletten Record übergeben/zuweisen - dann klappt es:
Delphi-Quellcode:
var TempVector : TVector;
begin
  TempVector := Probe.r0;
  TempVector.x := 3;
  Probe.r0 := TempVector;
end;

Jelly 12. Jan 2004 08:59

Re: Ein Record als Property in einer Klasse
 
Zitat:

Zitat von Leuselator
Das ist der Sinn von Properties: die Objektdaten vor direktem Zugriff von aussen zu schützen!

Komisch. Ein Record ist doch kein Objekt? Versteh diese Logik nicht ganz von Borland, zumal das Lesen ja funktioniert. Mach ichs halt über Umweg. Danke für deine rasche Stellungsnahme.

Gruss,
Tom

choose 12. Jan 2004 10:14

Re: Ein Record als Property in einer Klasse
 
Hallo Jelly,

es geht bei Diesem Ansatz im Wesentlichen um die Einhaltung von gültigen Invarianten, die eine logiklose Struktur, wie ein Record, nicht gewährleisten kann.
Darüber hinaus sollte die Schnittstelle (hier: zugänglich durch Properties) nichts über die konkrete Implementierung aussagen. Tatsächlich ist es nicht notwendig, dass eine Klasse eine Exemplarvariable für den Strukturierten Datentyp besitzt.

Im folgenden Beispiel beschreibe ich eine Klasse zur Darstellung eines Quadrats, die eine Eigenschaft Bounds besitzt. Sie gibt Auskünft über das kleinste umschließende Rechteck des dargestellten Quadrats. Selbstverständlich entspricht der Wert beim lesenden Zugriff immer dem Quadrat selbst, beim schreiben jedoch, sollte das Quadrat angepasst werden (Setzen der Quadratkantenlänge auf die kleiner der beiden Seiten des umschließenden Rechtecks). Es ist offensichtlich unnötig, die beiden Seitenlängen des Rechtecks zu speichern.
Folgende Besonderheit ist in diesem Beispiel vorgesehen: Sollten beide Längen des umschließenden Rechtecks negativ sein, werden die beiden Längen invertiert betrachtet (andernfalls macht das Bsp wg der Invarianten keinen Sinn ;))
Delphi-Quellcode:
type
  TMySquare = class
  private
    FLen: Double;
    function GetBounds: TPoint;
    procedure SetBounds(const AValue: TPoint);
  public
    property Bounds: TPoint
      read GetBounds
      write SetBounds;
  end;

function TMySqare.GetBounds: TPoint;
begin
  Result:= Point(FLen, FLen);
end;

procedure TMySquare.SetBounds(const AValue: TPoint);
begin
  with AValue do
  begin
    // only same sign and not null
    if Math.Sign(X)*Math.Sign(Y)<>1 then
      raise EInvalidArgument...
 
    Self.FLen:= Min(Abs(X), Abs(Y));
  end;
end;
An diesem Beispiel kann nun gezeigt werden, dass Zugriffe auf Felder des Records nicht eindeutig realisiert werden können:
Delphi-Quellcode:
mySquare.Bounds:= Point(10, 10); //FLen=10
mySquare.Bounds:= Point(-5, -2); //FLen=2
myPoint:= mySquare.Bounds; // myPoint=(2, 2)
mySquare.Bounds.X:= 1; // ???
Solltest Du hingegen einen Zugriff der Art
Delphi-Quellcode:
mySquare.Bounds.X:= myValue;
benötigen, kannst Du dies durch eine Hilfsklasse, die von TPersistent abgeleitet wird, realisieren. Die Eigenschaft Font der Klasse TControl ist bspw so realisiert.

Jelly 12. Jan 2004 10:20

Re: Ein Record als Property in einer Klasse
 
Danke choose für die ausführlich Schilderung. Habs jetzt kapiert.

Das mit TPersistent war mir bekannt. Mir ging es lediglich um die Record Datenstruktur, was mich anfanglich doch sehr verwundert hat, warum das Schreiben fehlschlug. An deinem Beispiel ist das aber klar nachzuvollziehen.

Übrigens ist nicht mal die Klasse TPersistent nötig. Eine einfach TClass reicht schon vollkommen aus.

Gruß,
Tom

choose 12. Jan 2004 10:28

Re: Ein Record als Property in einer Klasse
 
Hallo Jelly,

schön, dass ich Dir helfen konnte. Für Änderungen zur Laufzeit ist tatsächlich eine beliebige Klasse ausreichend, um einzelne Felder ändern zu können. Zur Designzeit müssen Properties allerdings als published deklariert und die aggregierten Klassen zusätzlich mit RTTI (Reflektions-/Introspektionscode) kompiliert worden sein, damit der OI mit ihnen arbeiten kann. Diese Forderung erfüllst Du dabei entwerder mit der lokalen Kompileroption {$M+} oder durch Erben von der Klasse TPersistent.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:52 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz