Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Gemischte Verwendung von Class und TRecord (https://www.delphipraxis.net/194197-gemischte-verwendung-von-class-und-trecord.html)

norwegen60 27. Okt 2017 08:37

Gemischte Verwendung von Class und TRecord
 
Hallo zusammen,

ich habe ein paar ältere Threads zu diesem Thema gefunden, wollte aber mal ein kurzes Feedback, ob sich hier etwas geändert hat.

Die Frage ist, was für/gegen eien gemischet Verwendung von Klassen und Records spricht. Hier die beiden Code-Varianten:

Delphi-Quellcode:
Type
  TPosition = record
    X, Y, Z: Integer;
  end;

  TTest = class
  private
    FNr: Integer;
    FName: String;
    FPosition: TPosition;
    procedure SetNr(iNumber: Integer);
  public
    property Nr: Integer read FNr write SetNr;
    property Name: String read FName write FName;
    constructor Create;
    destructor Destroy; override;
  end;
oder die reine Klassen-Variante
Delphi-Quellcode:
Type
  TPosition = Class
    FX, FY, FZ: Integer;
  public
    property X: Integer read FX write FX;
    property Y: Integer read FY write FY;
    property Z: Integer read FZ write FZ;
    constructor Create;
    destructor Destroy; override;
  end;

  TTest = Class
  private
    FNr: Integer;
    FName: String;
    FPosition: TPosition;
    procedure SetNr(iNumber: Integer);
  public
    property Nr: Integer read FNr write SetNr;
    property Name: String read FName write FName;
    constructor Create;
    destructor Destroy; override;
  end;
Ich sehe in der zweiten Variante zunächst vor allem den Mehraufwand
  • in der Deklaration
  • dass ich auch für TPosition zusätzlich Create/Destroy aufrufen muss
Vorteile sehe ich eigentlich nicht.

TTest steht nicht zur Diskusion. Hier habe ich in obigem Code nur einen Bruchteil der Funktionalität dargestellt.

Danke für euer Feedback
Gerd

Stevie 27. Okt 2017 09:00

AW: Gemischte Verwendung von Class und TRecord
 
Dein TPosition ist ein sogenanntes Value Object.

Berücksichtigt man deren Eigenschaft der Unveränderbarkeit (ich kann nicht einfach nur X, Y oder Z ändern) merkt man bei der Speicherverwaltung von Delphi, dass man sich dann oft um das Freigeben, des vorherigen Objekts kümmern muss, wenn man eine neue TPosition erzeugt und zuweist. Daher bietet sich hierfür eher die Verwendung von Records an. (bei Sprachen mit GC oder anderer automatischer Speicherverwaltung ergibt sich dieses Problem nicht, daher werden dort auch oft Klassen statt Records/Structs benutzt)

Außerdem kann man bei Records einfacher implizite oder explizite Typkonvertierung durch Operatorüberladung einbauen.

Das könnte zur Folge haben, dass man auch beim Record private Felder, öffentliche readonly Eigenschaften und ggf einen Konstruktor benutzt.

sakura 27. Okt 2017 09:44

AW: Gemischte Verwendung von Class und TRecord
 
Gerne wird vergessen, dass in Delphi auch Folgendes für Records möglich ist:
Delphi-Quellcode:
type
  TPosition = record
  private
    FX, FY, FZ: Integer;

    procedure SetX(const Value: Integer);
    procedure SetY(const Value: Integer);
    procedure SetZ(const Value: Integer);
  public
    property X: Integer read FX write SetX;
    property Y: Integer read FY write SetY;
    property Z: Integer read FZ write SetZ;
  end;
Damit hat man dann auch Kontrolle über Veränderungen - in diesem Beispiel wahrscheinlich nicht sinnvoll, aber man sollte es im Hinterkopf haben. Und dann sind Records wirklich ein praktisches Mittel für die Value Objekte.

...:cat:...

Stevie 27. Okt 2017 12:17

AW: Gemischte Verwendung von Class und TRecord
 
Zitat:

Zitat von sakura (Beitrag 1384320)
man sollte es im Hinterkopf haben. Und dann sind Records wirklich ein praktisches Mittel für die Value Objekte.

Gerade nicht, Value Objekte sind per Definition unveränderlich, d.h. es gibt keine Setter um einzelne Eigenschaften zu ändern.
Was im Zusammenhang mit Records auch gut ist, da es so nicht so Code wie diesem kommen kann:

Delphi-Quellcode:
test.Position.X := test.Position.X + 10;
Und man sich dann wundert, warum es nicht mehr funktioniert nachdem man für die Position Eigenschaft einen Getter geschrieben hat
(weil man nun X einer Kopie - Records sind Value types - ändert)

Sherlock 27. Okt 2017 12:26

AW: Gemischte Verwendung von Class und TRecord
 
Ich bin jetzt vielleicht blöd, aber wieso ist TPosition ein ValueObject?

Sherlock

Stevie 27. Okt 2017 12:48

AW: Gemischte Verwendung von Class und TRecord
 
Zitat:

Zitat von Sherlock (Beitrag 1384330)
Ich bin jetzt vielleicht blöd, aber wieso ist TPosition ein ValueObject?

Der deutsche Wikipedia Eintrag ist da möglicherweise nicht so klar wie die englische Beschreibung:

Zitat:

Zitat von en.wikipedia.org
In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.

Bei einer Position ist in aller Regel: (4,5,6) = (4,5,6) auch wenn das zwei unterschiedliche Instanzen/Entitäten sind. Wenn nun aber 2 Objekte in einem Koordinatensystem an derselben Position sind und eins davon sich ändert, weise ich ihm eine neue Position zu (auch, wenn sich nur X, Y oder Z geändert hat). Hätte ich möglicherweise Objekte dafür, ergäbe sich die Gefahr, dass es sich um dieselben Instanzen handelt, weil ich irgendwo geschrieben habe:

Delphi-Quellcode:
pos := TPosition.Create(4, 5, 6);
obj1.Pos := pos;
obj2.Pos := pos;
Angenommen ich habe nun noch Setter für X, Y, Z. Wenn ich nun
Delphi-Quellcode:
obj1.Pos.X := 7;
schreibe, ändert sich dann die Position von obj2 möglicherweise auch.

sakura 27. Okt 2017 13:23

AW: Gemischte Verwendung von Class und TRecord
 
Zitat:

Zitat von Stevie (Beitrag 1384329)
Gerade nicht, Value Objekte sind per Definition unveränderlich, d.h. es gibt keine Setter um einzelne Eigenschaften zu ändern.

Sorry, stimmt. Aber gerade da ist es dann sinnvoll diese einmalig zu initialisieren und dann die Werte nur noch über read-only Properties zu ermitteln. :oops:
Delphi-Quellcode:
type
  TPosition = record
  private
    FX, FY, FZ: Integer;
  public
    class function New(const aX, aY, aZ: Integer): TPosition; static;

    property X: Integer read FX;
    property Y: Integer read FY;
    property Z: Integer read FZ;
  end;

class function TPosition.New(const aX, aY, aZ: Integer): TPosition;
begin
  Result.FX := aX;
  Result.FY := aY;
  Result.FZ := aZ;
end;
...:cat:...

Sherlock 27. Okt 2017 13:42

AW: Gemischte Verwendung von Class und TRecord
 
Danke, Stevie!

Sherlock


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:57 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