Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder (https://www.delphipraxis.net/201535-record-array-als-property-einer-klasse-einfacher-zugriff-auf-die-record-felder.html)

changlee 30. Jul 2019 10:09

Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Hallo,

ich glaube ich habe ein ganz einfaches Problem aber mir fällt keine vernünftige Lösung ein.

Das Feld fJobs meiner Klasse TJoblist ist ein dynamisches Record-Array.
Wie kann ich von außen auf die Felder des Records lesend und schreiben zugreifen?

Code:
TStrArray         = array of string;

TJobData = record
    Name:          string;
    uid:           integer;
    sources:       TStrArray;
end;

TJobList = class(TObject)
  private
    fJobs: array of TJobData;
    procedure SetJob(jobIndex: integer; const job:TJobData);
    function GetJob(jobIndex: integer):TJobData;
  public
    property Jobs[jobIndex: integer]: TJobData read GetJob write SetJob; //???? die eigenschaften des jobs können dennoch beschrieben werden! (soll auch so sein)
  end;
Idealerweise würde ich gern wie folgt darauf zugreifen:
Code:
joblist.Jobs[1].Name := joblist.Jobs[1].Name + ' TEST';
Beim Lesen und insbesondere beim Schreiben möchte ich aber in der Klasse über Set- und Get-Methoden die Kontrolle darüber behalten, was gelesen und geschrieben wird.
Eine Idee war statt des Records einen Pointer auf den Record zurückzugeben. Aber dann bekomme ich ja vom Schreiben nichts mehr mit, oder?

So wie es aktuell implementiert ist, benötige ich mehrere Zeilen um eine Job.Eigenschaft zu verändern:
Code:
job := joblist.Jobs[1];
job.Name := job.Name + ' TEST';
joblist.Jobs[1] := job;
Gibts einen besseren Weg?

Viele Grüße
Stefan

Der schöne Günther 30. Jul 2019 10:14

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Dein Record ist ein Werttyp- kein Referenztyp. Wenn du etwas hier nach außen gibst, dann eine Kopie des Records, wie du ja schon bemerkt hast.

Entweder du lässt die Properties weg und gibst das reine Array nach außen oder du kommst um Methoden wie
Delphi-Quellcode:
setJobName(jobIndex, jobName)
nicht herum.

DieDolly 30. Jul 2019 10:16

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Ich würde an deiner Stelle eher eine generische TObjectList nehmen statt eines Arrays.

Der schöne Günther 30. Jul 2019 10:21

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
In eine TObjectList Records reinstecken klingt interessant.

DieDolly 30. Jul 2019 10:23

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Ist doch vollkommen egal. Jeder sollte verstehen was ich meine und auch sehen, dass das Beispiel aus Beitrag 1 nicht gut ist.
Außerdem habe ich nicht geschrieben, dass ich Records in eine TObjectList stecken würde.

Olli73 30. Jul 2019 10:48

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Warum nicht gleich aus dem record eine Klasse machen?

Der schöne Günther 30. Jul 2019 10:51

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Mal eben so aus einem Wertetyp einen Referenztyp machen ist meist nicht mal eben so getan. Wenn sich jemand bislang über die öffentliche Property ein paar
Delphi-Quellcode:
TJobData
geholt hat, dann hatte er eine Kopie.

Stellt man das jetzt um, hat er nur noch eine Referenz. Und angenommen diese Jobs sollen wirklich der TJobList gehören, muss man auch sicherstellen dass niemand mehr auf die abgeholten Referenzen zugreift sobald die Liste abgeräumt wird. Ich finde das nicht so trivial wie es klingt.

changlee 30. Jul 2019 10:58

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Zitat:

Zitat von Olli73 (Beitrag 1438375)
Warum nicht gleich aus dem record eine Klasse machen?

Da kome ich her. Das ganze war viel umfangreicher, allgemeiner und wiederverwendbarer, aber es war auch eine Nummer zu groß, so dass es einfach nicht fertig geworden ist.
Ich habe das ganze Projekt jetzt etwas kleiner aufgesetzt und es soll so einfach wie möglich gehalten werden.

Zitat:

Zitat von DieDolly (Beitrag 1438367)
Ich würde an deiner Stelle eher eine generische TObjectList nehmen statt eines Arrays.

Ich hatte zuvor eine TList. Aber da habe ich im Prinzip das gleiche Problem. Die Felder des Records konnten dann geändert werden, ohne dass die joblist davon etwas mitbekam.

Zitat:

Zitat von Der schöne Günther (Beitrag 1438366)
Entweder du lässt die Properties weg und gibst das reine Array nach außen oder du kommst um Methoden wie
Delphi-Quellcode:
setJobName(jobIndex, jobName)
nicht herum.

Ich denke so werde ich es machen. Ist zwar nicht ganz so kurz, wie ich mir vorgestellt hatte, aber es ist ok.

Danke!

DieDolly 30. Jul 2019 11:11

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Zitat:

Ich hatte zuvor eine TList. Aber da habe ich im Prinzip das gleiche Problem. Die Felder des Records konnten dann geändert werden, ohne dass die joblist davon etwas mitbekam.
Guck dir mal an wie das in der Unit System.IniFiles; gemacht wurde. Da gibt es das Property Modified.
Wenn du das Record komplett weglässt und eine ordentliche Klasse mit Properties baust und dann noch irgendwas mit einem Modified-Property dann solltest du haben was du suchst.

Zitat:

Ich denke so werde ich es machen. Ist zwar nicht ganz so kurz, wie ich mir vorgestellt hatte, aber es ist ok.
Ich wprde das Record weglassen und gleich Properties in die Klasse einbauen.

Blup 7. Aug 2019 09:55

AW: Record-Array als Property einer Klasse: einfacher Zugriff auf die Record-Felder
 
Die Umstellung auf einen Referenztyp ist für dieses Problem oft die einfachste und schnellste Lösung, aber nicht unbedingt die Beste.
Delphi-Quellcode:
type
  TStrArray = array of string;

  PJobData = ^TJobData;
  TJobData = record
    Name:         string;
    uid:          integer;
    sources:      TStrArray;
    procedure Assign(const AItem: TJobData);
  end;

  TJobList = class(TObject)
  private
    fJobs: array of TJobData;
    procedure SetJob(jobIndex: integer; job: PJobData);
    function GetJob(jobIndex: integer): PJobData;
  public
    property Jobs[jobIndex: integer]: PJobData read GetJob write SetJob;
  end;

implementation

procedure TJobData.Assign(const AItem: TJobData);
begin
  Name := AItem.Name;
  uid := AItem.uid;
  // damit sources und AItem.sources nicht auf das selbe Array verweisen
  // und nachfolgende Änderungen von AItem.sources keine Auswirkungen auf sources haben
  sources := Copy(AItem.sources);
end;

procedure TJobList.SetJob(jobIndex: integer; job: PJobData);
begin
  {...}
//  fJobs[i] := job^;
  fJobs[i].Assign(job^);
end;
   
function TJobList.GetJob(jobIndex: integer): PJobData;
begin
  {...}
  Result := @(fJobs[i]);
end;


joblist.Jobs[1]^.Name := joblist.Jobs[1]^.Name + ' TEST';


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