![]() |
Ein Record als Property in einer Klasse
Hallo zusammen,
hab ein skurieles Problem. Folgender Code:
Delphi-Quellcode:
Probier ich jetzt mittels
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 ;
Delphi-Quellcode:
einen Wert zuzuweisen, krieg ich ne Fehlermeldung beim Kompilieren:
Probe.r0.x := 3 ;
Zitat:
Wer weiß da Rat? Gruß, Tom |
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; |
Re: Ein Record als Property in einer Klasse
Zitat:
Gruss, Tom |
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:
An diesem Beispiel kann nun gezeigt werden, dass Zugriffe auf Felder des Records nicht eindeutig realisiert werden können:
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;
Delphi-Quellcode:
Solltest Du hingegen einen Zugriff der Art
mySquare.Bounds:= Point(10, 10); //FLen=10
mySquare.Bounds:= Point(-5, -2); //FLen=2 myPoint:= mySquare.Bounds; // myPoint=(2, 2) mySquare.Bounds.X:= 1; // ???
Delphi-Quellcode:
benötigen, kannst Du dies durch eine Hilfsklasse, die von TPersistent abgeleitet wird, realisieren. Die Eigenschaft Font der Klasse TControl ist bspw so realisiert.
mySquare.Bounds.X:= myValue;
|
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 |
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 04:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz