Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Record im Array nutzen? - Sinnvollere Wege? (https://www.delphipraxis.net/185842-record-im-array-nutzen-sinnvollere-wege.html)

Asura 10. Jul 2015 15:05

Record im Array nutzen? - Sinnvollere Wege?
 
Guten Tag,
zurzeit benutze ich ein Array, welches ein Element eines Records ist.
Nur habe ich gerade bei meinen Recherchen erfahren, dass dies keine schöne Methode ist.
Also mein Record sieht so aus:

Delphi-Quellcode:
    TEmployee = Record                          
                  CardID       : Integer;
                  Prename,
                  Surname,
                  Workstation,
                  Position     : String[100];
                  Birthdate    : TDate;
                  AvailAbility : Array[1..7] of String;
                End;
Das Array besteht aus 40 Feldern, die jeweils ja diese Record Anordnung haben.

Nun Frage ich mich, ist dieser Weg, wie ich ihn gewählt habe, in Ordnung, oder gibt es bessere Methoden dies umzusetzen?

MfG
Asura

jaenicke 10. Jul 2015 15:38

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Wie wäre es mit Objekten in einer TObjectList?
Also TEmployee = class und die Liste je nach Delphiversion deklariert als TObjectList oder wenn möglich besser TObjectList<TEmployee>.

Vorteile sind, dass du Teile der Objekte anders als bei Records auch direkt setzen kannst über die Liste und dass du eine beliebige Anzahl an Elementen hast ohne das Array manuell in der Größe verändern zu müssen.

p80286 10. Jul 2015 16:26

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Eine Liste ist zunächst einmal eine gute Alternative.
Ich würde aber erst einmal tiefer ansetzen und die Elemente des Records kritisch hinterfragen.
a) ist die CardId wirklich numerisch? oder sieht sie nur so aus?
b) was verbirgt sich hinter Position? wenn dies festgelegte Inhalte sind, dann wäre es nicht schlecht z.B. mit ENUM-Typen zu arbeiten. sonst läuft die Suche nach "Hausmeister" ins Leere weil da jetzt der "Facility Manager" steht.
c) Wenn Du
Delphi-Quellcode:
  Position : String[100];
nutzt dann wenigstens auch
Delphi-Quellcode:
AvailAbility : Array[1..7] of AnsiString;
oder
Delphi-Quellcode:
AvailAbility : Array[1..7] of String[255];
Sonst ist das Character-Chaos vorprogrammiert.

Gruß
K-H

Union 10. Jul 2015 16:42

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Ich habe die schreckliche Vermutung dass sich hinter Availability die Verfügbarkeit an einem bestimmten Wochentag verbirgt. Hier wäre ja dann wohl eher so etwas sinnvoll (abgesehen dass es dann in 8 Bit statt in 8 Byte gespeichert werden kann):

Delphi-Quellcode:
TWeekDays = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday);
TAvailability = set of TWeekDays;

Asura 10. Jul 2015 17:36

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Hallo,
Dankeschön erstmal für die Antworten. Ich habe mal im Anhang das ganze Projekt angehängt, sodass ihr euch mal ein Bild machen könnt (Im Source Ordner zu finden).
Ich habe es zurzeit über meine Methode gelöst - zwar mit mehreren Stunden Ärgernissen, aber schlussendlich gelöst. Aber auch nur die Mitarbeiterverwaltung zum großteil.

Zu den Availability: Ja das sind Tage. Ich habe das so gelöst, dass der Index 1 Beispielsweise für Montag steht und der hintergelegte Text "17:00-23:00" beispielsweise gesplittet und aufgeteilt wird.

Alle Werte sollten Variabel gehalten werden, sprich in meiner aktuellen Version lassen sich alle bearbeiten. Auch Position.

Und Card ID benutze ich zum Teil dafür um meine Items im Array zu finden, sie dient aber auch für den Anwender Informationsgrundlage, die bei der Eintragung wichtig ist.


Ich würde mich auch sehr freuen, wenn ihr generell paar Kritik Äußerungen zu den Programmcode mir schreiben könntet und was ich da verbessern kann oder komplett verändern muss. Würde mich sehr freuen!

MfG
Asura

Sir Rufo 10. Jul 2015 18:33

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Ich hätte das mit Klassen so aufgebaut
Delphi-Quellcode:
unit Unit1;

interface

uses
  System.Classes,
  System.DateUtils,
  System.Generics.Collections,
  System.TimeSpan;

type
{$SCOPEDENUMS ON}
  TWeekDay = ( Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday );
{$SCOPEDENUMS OFF}

  TAvailibility = class( TPersistent )
  private
    FFrom: TTime;
    FDuration: TTimeSpan;
    FIsAvailable: Boolean;
    procedure SetFrom( const Value: TTime );
    procedure AssignToAvailibility( Dest: TAvailibility );
    procedure SetIsAvailable( const Value: Boolean );
  protected
    procedure AssignTo( Dest: TPersistent ); override;
  public
    function Equals( Obj: TObject ): Boolean; override;

    property IsAvailable: Boolean read FIsAvailable write SetIsAvailable;
    property From: TTime read FFrom write SetFrom;
    property Duration: TTimeSpan read FDuration write FDuration;
  end;

  TEmployee = class( TPersistent )
  private
    FAvailibility: TObjectDictionary<TWeekDay, TAvailibility>;
    FCardID: Integer;
    FPrename: string;
    FSurname: string;
    FWorkstation: string;
    FPosition: string;
    FBirthday: TDate;
    function GetAvailibility( Weekday: TWeekDay ): TAvailibility;
    procedure SetBirthday( const Value: TDate );
    procedure AssignToEmployee( Dest: TEmployee );
    procedure SetAvailibility( Weekday: TWeekDay; const Value: TAvailibility );
  protected
    procedure AssignTo( Dest: TPersistent ); override;
  public
    constructor Create;
    destructor Destroy; override;

    function Equals( Obj: TObject ): Boolean; override;

    property CardID: Integer read FCardID write FCardID;
    property Prename: string read FPrename write FPrename;
    property Surname: string read FSurname write FSurname;
    property Workstation: string read FWorkstation write FWorkstation;
    property Position: string read FPosition write FPosition;
    property Birthday: TDate read FBirthday write SetBirthday;
    property Availibility[ Weekday: TWeekDay ]: TAvailibility read GetAvailibility write SetAvailibility;
  end;

implementation

{ TEmployee }

procedure TEmployee.AssignTo( Dest: TPersistent );
begin
  if ( Dest is TEmployee ) then
    AssignToEmployee( Dest as TEmployee )
  else
    inherited;
end;

procedure TEmployee.AssignToEmployee( Dest: TEmployee );
var
  LWeekDay: TWeekDay;
begin
  Dest.FCardID := Self.FCardID;
  Dest.FPrename := Self.FPrename;
  Dest.FSurname := Self.FSurname;
  Dest.FWorkstation := Self.FWorkstation;
  Dest.FPosition := Self.FPosition;
  Dest.FBirthday := Self.FBirthday;
  for LWeekDay := low( TWeekDay ) to high( TWeekDay ) do
    Dest.SetAvailibility( LWeekDay, Self.GetAvailibility( LWeekDay ) );
end;

constructor TEmployee.Create;
var
  LWeekDay: TWeekDay;
begin
  inherited Create;
  FAvailibility := TObjectDictionary<TWeekDay, TAvailibility>.Create( [ doOwnsValues ] );
  for LWeekDay := low( TWeekDay ) to high( TWeekDay ) do
  begin
    FAvailibility.Add( LWeekDay, TAvailibility.Create );
  end;
end;

destructor TEmployee.Destroy;
begin
  FAvailibility.Free;
  inherited;
end;

function TEmployee.Equals( Obj: TObject ): Boolean;
begin
  Result := ( Self = Obj ) or Assigned( Obj ) and ( Obj is TEmployee ) and ( TEmployee( Obj ).FCardID = Self.FCardID );
end;

function TEmployee.GetAvailibility( Weekday: TWeekDay ): TAvailibility;
begin
  Result := FAvailibility[ Weekday ];
end;

procedure TEmployee.SetAvailibility( Weekday: TWeekDay; const Value: TAvailibility );
begin
  FAvailibility[ Weekday ].Assign( Value );
end;

procedure TEmployee.SetBirthday( const Value: TDate );
begin
  FBirthday := DateOf( Value );
end;

{ TAvailibility }

procedure TAvailibility.AssignTo( Dest: TPersistent );
begin
  if ( Dest is TAvailibility ) then
    AssignToAvailibility( Dest as TAvailibility )
  else
    inherited;
end;

procedure TAvailibility.AssignToAvailibility( Dest: TAvailibility );
begin
  Dest.FFrom := Self.FFrom;
  Dest.FDuration := Self.FDuration;
end;

function TAvailibility.Equals( Obj: TObject ): Boolean;
begin
  Result := ( Self = Obj ) or Assigned( Obj ) and ( Obj is TAvailibility ) and (
    {} ( TAvailibility( Obj ).FIsAvailable = Self.FIsAvailable ) or
    {} ( ( TAvailibility( Obj ).FFrom = Self.FFrom ) and ( TAvailibility( Obj ).FDuration = Self.FDuration ) ) );

end;

procedure TAvailibility.SetFrom( const Value: TTime );
begin
  FFrom := TimeOf( Value );
end;

procedure TAvailibility.SetIsAvailable( const Value: Boolean );
begin
  FIsAvailable := Value;
end;

end.

Namenloser 10. Jul 2015 18:39

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Also zunächst mal ist zu sagen, dass es in Delphi seit Version 4 bereits dynamische Arrays gibt. Es gibt also keinen Grund, eine Maximalgröße wie „1000“ fest vorzugeben. Feste Größen sind schlecht, weil sie erstens beliebig sind (warum gerade 1000? Was ist, wenn es 1001 Mitarbeiter gibt?) und zweitens, weil sie Platz verschwenden. Schreibe statt
Delphi-Quellcode:
Employees: array[1..1000] of TEmployee
also besser
Delphi-Quellcode:
Employees: array of TEmployee
. Die Größe kannst du mit SetLength zur Laufzeit verändern.

Da es aber mühsam ist, jedes mal beim Hinzufügen eines Elements (vom Löschen fangen wir gar nicht erst an) folgendes zu schreiben
Delphi-Quellcode:
SetLength(Employees, length(Employees)+1);
Employees[length(Employees)-1] := NewEmployee;
verwendet man besser eine TObjectList oder TList.

Das mit der festen Höchstlänge gilt auch für Strings. Wenn es nicht wirklich einen guten Grund gibt, dann sollte man nicht
Delphi-Quellcode:
String[100]
schreiben, sondern einfach
Delphi-Quellcode:
String
.

Als Grundproblem sehe ich bei dir die aber die mangelnde Modellierung an.

Zunächst mal solltest du die Geschäftslogik strikt von der Darstellung trennen. Du solltest also Termine, Uhrzeiten etc. z.B. intern niemals als String speichern. Statt einen einzelnen Termin ("15:00-17:30") als String zu repräsentieren, der immer wieder geparst werden muss, bastel dir einen speziellen Typen, der genau die Information abbildet:
Delphi-Quellcode:
TAppointment = record
  StartTime: TTime;
  EndTime: TTime;
end;
[...]

Availability : Array[1..7] of TAppointment;
Dann der nächste Punkt:
Delphi-Quellcode:
Array[1..7]
. Zunächst mal fangen Arrays normalerweise bei 0 an und nicht bei 1. Davon abzuweichen führt eher zu Verwirrungen und Fehlern. Noch wichtiger: Die Zahlen sagen mir nichts über die Bedeutung. Ich kann nur mutmaßen, dass es sich hier um Wochentage handelt. Aber dann ist immer noch die Frage, welche Zahl welchem Tag entspricht. Entspricht die 1 z.B. dem Montag oder dem Sonntag?

Besser wäre:

Delphi-Quellcode:
TWeekday = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday);

Availability: Array[TWeekday] of TAppointment;
Das sieht schon besser aus.

Allerdings ist diese Modellierung jetzt natürlich immer noch darauf eingeschränkt, dass es pro Wochentag nur einen Termin gibt. Da kann ich jetzt ohne nähere Informationen zu deinem Anwendungsfall nicht sagen, ob das zu deinem Anwendungsfall passt oder nicht.

Aber selbst dann wäre es eventuell besser, einfach eine flache Liste von Terminen zu speichern, die nicht nach Wochentagen gruppiert ist:

Delphi-Quellcode:
TAppointment = record
  StartTime: TDateTime; // Beachte: Nun DateTime
  EndTime: TDateTime;
end;

[...]

Availability: array of TAppointment;
// &#959;der bei neueren Delphis
Availability: TList<TAppointment>;
So ist man, falls sich die Anforderungen später doch mal ändern, flexibler mit der Art von Terminen, die möglich sind. Man könnte z.B. mehrere Termine an einem Tag haben. Durch hinzufügen eines zusätzlichen Feldes zu TAppointment könnte man sogar unterscheiden zwischen einmaligen Terminen und solchen, die sich jede Woche wiederholen.

Asura 10. Jul 2015 23:46

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Erstmal vielen Dank für die bis jetzt aufgebrachte Mühe!

Ich muss vorab sagen, ich mach das alles nur als Hobby, bin nebenbei noch Schüler und interessiere mich in den Bereich und würde auch gerne in der Richtung studieren wollen und will mir bereits fürs Studium mal schon ein gewisses Basiswissen schaffen.

Nun wo fange ich erstmal an. Ich habe mir mal den Programmaufbau von Sir Rufo angeschaut. Ich muss sagen, dass ist für mein Anfängerwissen echt zu hoch. Also da fallen mir viele Fragen ein, wobei ich das mal nur auf das allgemeinste begrenze:
  1. Diese Darstellung ist nicht mit TObjects zu vergleichen, oder ist genau das eine Form von den bereits genannten TObjects?
  2. Spricht man von anderen Units dann genau diese einzelne Unterklasse an und die damit verbundenen Prozeduren und Funktionen?
  3. Was hat es mit der Funktion "Equals" auf sich?
  4. Warum muss man TEmployee im Destruktor wieder freigeben?
  5. Was hat es mit diesem {$SCOPEDENUMS ON} auf sich?

Ich muss sagen, dass dieses Codebeispiel, nochmals danke für diese Mühe extra auf mein Fallbeispiel angepasst eine Unit zu verfassen, für mich eine zu Hohe Hausnummer ist, man vergleiche mal meine Version (Um mal auf Deutsch zu sagen "ein Scheiß dagegen" ist.)

Ich habe mich mal desweiteren informiert und muss sagen, dass TObjects sich auf jedenfall besser eignet als meine Method, die wie von euch genannt, zu stark auf die Darstellung ausrichtet ist.

Nun zu Namenloser:
Bezüglich dem Array, ich gebe dir absolut Recht bezüglich dem Dynamischen Array und würde auch hier lieber TObjectlist nutzen. Also an meinem Anwendungsfall, wird pro Wochentag nur ein Termin genutzt. Denn später werde ich mit der Zeit schauen, ob die betroffene Person an dem Wochentag in einem bestimmten Zeitraum verfügbar ist und dabei wird nur dieser Zeitwert für den einen Wochentag genutzt.

Bezüglich 0 und 1 im Array. Ich habe das eig benutzt, damit ich später noch weiß, dass damit von Montag bis Sonntag gemeint ist (7 Tage). Aber die vorgeschlagene Methode ist um einiges besser.
Aber ich muss auch später Urlaubstage einfügen, also ich habe mir einfach gedacht, dass ich diese Tage in eine TStringlist reinschreibe und das Programm einfach die Liste durchgeht und wenn der Tag mit dem Tag der Überprüfung übereinstimmt, wird dieser als nicht verfügbar angezeigt.

Eine schlussendliche Frage habe ich noch: Als Grundproblem soll meine mangelnde Modellierung schuld sein, kann ich dies irgendwo nachlesen bzw. lernen? Eventuell habt ihr dazu passendes Informationsmaterial zur Hand? Würde gerne daran arbeiten wollen.

MfG
Asura

Namenloser 11. Jul 2015 11:17

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von Asura (Beitrag 1308362)
Eine schlussendliche Frage habe ich noch: Als Grundproblem soll meine mangelnde Modellierung schuld sein, kann ich dies irgendwo nachlesen bzw. lernen? Eventuell habt ihr dazu passendes Informationsmaterial zur Hand? Würde gerne daran arbeiten wollen.

Hmm, ich kann dir nicht wirklich etwas bestimmtes empfehlen, aber generell Bücher über Objektorientierung. Muss nicht unbedingt ein Buch zum Kaufen sein, habe selber auch nie eins besessen (wobei das Buch „Delphi für Kids“, mit dem ich damals den Einstieg in die Programmierung gefunden habe, schon etwas Objektorientierung mitbehandelte). Im Internet gibt es sehr viel Material dazu. Kann leider wie gesagt kein bestimmtes empfehlen, ist bei mir selber zu lange her. Aber vielleicht hat ja jemand anders einen Tipp.

Wenn du Objektorientierung verinnerlicht hast, schau dir als nächstes Design Patterns an.

Bjoerk 11. Jul 2015 11:38

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zur Not kannst du auch erst mal beim Record bleiben, dann mußt du dein Programm nicht komplett neu machen. Records sind aus mehren Gründen allerdings nicht zu empfehlen. Der String[100] kann auch irgendwann mal ein string werden, wenn du satt typisierte Dateien (Annahme) z.B. einen FileStream oder zur Not auch eine MemIniFile verwendest.
Delphi-Quellcode:
  TEmployees = class
  private
    function GetCount: integer;
    procedure SetCount(const Value: integer);
  public
    Items: array of TEmployee;
    property Count: integer read GetCount write SetCount;
    function Add(const Value: TEmployee): integer;
    procedure Delete(const Index: integer);
    procedure Assign(Value: TEmployees);
    procedure Clear;
    procedure LoadFromFile(const FileName: string);
    procedure SaveToFile(const FileName: string);
    destructor Destroy; override;
  end;

{ TEmployees }

destructor TEmployees.Destroy;
begin
  Clear;
  inherited;
end;

function TEmployees.GetCount: integer;
begin
  Result := Length(Items);
end;

procedure TEmployees.SetCount(const Value: integer);
begin
  SetLength(Items, Value);
end;

procedure TEmployees.Clear;
begin
  SetCount(0);
end;

function TEmployees.Add(const Value: TEmployee): integer;
begin
  Result := Count;
  SetCount(Result + 1);
  Items[Result] := Value;
end;

procedure TEmployees.Delete(const Index: integer);
var
  I: integer;
begin
  for I := Index to Count - 2 do
    Items[I] := Items[I + 1];
  SetCount(Count - 1);
end;

procedure TEmployees.Assign(Value: TEmployees);
var
  I: integer;
begin
  SetCount(Value.Count);
  for I := 0 to Count - 1 do
    Items[I] := Value.Items[I];
end;

procedure TEmployees.LoadFromFile(const FileName: string);
begin
end;

procedure TEmployees.SaveToFile(const FileName: string);
begin
end;

Sir Rufo 11. Jul 2015 12:20

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Die Persistenz-Schicht sollte aber nicht im Objekt selber sein.

Das gibt nachher einfach nur Kuddelmuddel, wenn man das Datenformat ändert/ändern muss (Umstieg von Dateien auf eine Datenbank).

Der Anwendung selber sollte es egal sein, wo die Daten abgelegt werden. Es gibt einfach einen Service, dem die Anwendung mitteilt, was mit dem Objekt passieren soll (CRUD). Der Service kümmert sich dann darum, wo diese Daten konkret abgelegt werden.

Der Aufwand ist nicht wirklich mehr als diese Verquickung, aber ungemein flexibel.

Asura 11. Jul 2015 13:07

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Wie könnte ich dann diese Persistenz-Schicht nach außen verlagern?
Und wie stelle ich da diese Informationen so bereit, dass dieser Service egal ist, ob diese in einer Datenbank oder File gespeichert werden?

Also wäre es ratsamer, wenn ich das Programm komplett neu überarbeite und nicht unbedingt nun ein Record nehme? Oder kann ich für meine Dimension des Programmes ruhig beim Record bleiben?

Namenloser 11. Jul 2015 14:26

AW: Record im Array nutzen? - Sinnvollere Wege?
 
@Sir Rufo: Das ist ja alles schön und gut, aber lass doch erst mal die Kirche im Dorf. Es macht keinen Sinn, jemandem, dem noch die Grundlagen der Objektorientierung fehlen, solche Konstrukte hinzuklatschen. Das führt nur zu Verwirrung. Von 0 auf 100 geht nun mal nicht sofort.

@Asura: Beim record lassen – kannst du zwar zur Not, bringt dich aber auch nicht weiter. Ich würde dir eher raten, dich einfach mal mit den Grundlagen objektorientierter Programmierung (Was ist eine Klasse? Was ist ein Objekt? Wann muss ich ein Objekt erzeugen und freigeben? Was ist Kapselung, Vererbung, Polymorphie?) zu befassen. Dann nutze dieses Wissen, um aus dem record eine Klasse und aus dem Array eine ObjectList zu machen. Dabei würde ich es dann auch erst mal belassen. In ein paar Jahren kannst du dich dann mit dem beschäftigen, was Sir Rufo geschrieben hat ;)

Asura 18. Jul 2015 19:23

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Guten Tag,
und zwar habe ich mich nun an der Klasse und an der Objectlist versucht:
Meine Klasse "Employee" hat die Properties, wie von Sir Rufo bereits vorgeschlagen.
Ich habe dann die Objectliste erstellt "OLEmployees".
Meine vorgehensweise sieht wie folgt aus:
Ich speichere in die Properties die Inhalte der Textfelder. Danach adde ich der Objectliste die Klasse Employee als neues Item dazu.

Die Initialisierungen und das Freigeben lasse ich hiermal weg, die finden in der Haupt-Unit im OnCreate und OnClose Event statt.

Delphi-Quellcode:
procedure TF_AddEditEmployee.btn_AddEditClick(Sender: TObject);
var EmployeeData: TStringlist;

begin

  EmployeeData := TStringlist.Create;

  EmployeeData.Add(edt_CardID.Text);
  EmployeeData.Add(edt_PreName.Text);
  EmployeeData.Add(edt_SurName.Text);
  EmployeeData.Add(DatetoStr(dt_Birthday.Date));
  EmployeeData.Add(edt_WorkStation.Text);
  EmployeeData.Add(edt_Position.Text);


      F_Employees.SelCardID := StrtoInt(edt_CardID.Text);

      try
        AddEmployeeData(F_Main.OLEmployees.Count, EmployeeData);

      except
        Messagebox(Self.Handle, 'Mitarbeiter konnte nicht hinzugefügt werden', 'Fehler',
                   MB_ICONWARNING or MB_OK);
      end;

      close;

  EmployeeData.Free;

end;

Delphi-Quellcode:
// *************************** Mitarbeiterhinzufügen ***************************

procedure AddEmployeeData(Index: Integer; EmployeeData: TStringlist);
begin

  F_Main.Employee.CardID     := StrtoInt(EmployeeData[0]);
  F_Main.Employee.Prename    := EmployeeData[1];
  F_Main.Employee.Surname    := EmployeeData[2];
  F_Main.Employee.Birthday   := StrtoDate(EmployeeData[3]);
  F_Main.Employee.Workstation := EmployeeData[4];
  F_Main.Employee.Position   := EmployeeData[5];

  F_Main.OLEmployees.Add(F_Main.Employee); // Employee Daten werden als neuer Eintrag gespeichert

end;
Meine Frage ist nun, ist das so richtig und wie kann ich nun wieder aus der Objectliste heraus das richtige Item finden? Ich kann ja schlecht IndexOf benutzen, da ja alle Items das gleiche Object (Employee) haben nur mit anderen Properties.
Zurzeit wäre ja jedes neue Item der Objectlist ein neuer Mitarbeiter mit den Eigenschaften von Employee.

Dalai 18. Jul 2015 19:44

AW: Record im Array nutzen? - Sinnvollere Wege?
 
@Asura: Warum dieser Umweg über die Stringliste?

MfG Dalai

p80286 19. Jul 2015 10:22

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von Asura (Beitrag 1309137)
Meine Frage ist nun, ist das so richtig und wie kann ich nun wieder aus der Objectliste heraus das richtige Item finden?

Na, so wie man es immer macht, nach property sortieren und dann suchen!?

Alternativ kann man auch entsprechende Indizes erstellen und über die dann den Zugriff steuern.

Gruß
K-H

Asura 19. Jul 2015 11:16

AW: Record im Array nutzen? - Sinnvollere Wege?
 
@Dalai:

Ich dachte mir für jede Property ein Parameter zu nehmen, wo ich den Inhalt eines Editfeldes übermittle ist unschön.
Oder gibt es eine andere Methode?

@p80286:

Muss ich mir dafür eine Funktion schreiben, oder wie kann ich nach der Property suchen?

Dejan Vu 19. Jul 2015 11:19

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von p80286 (Beitrag 1309152)
Zitat:

Zitat von Asura (Beitrag 1309137)
Meine Frage ist nun, ist das so richtig und wie kann ich nun wieder aus der Objectliste heraus das richtige Item finden?

Na, so wie man es immer macht, nach property sortieren und dann suchen!?

Immer?
1x suchen: Linear durchsuchen.
öfter suchen: Dictionary.
Sortieren und dann suchen? Ich jedenfalls nie.

Dalai 19. Jul 2015 12:03

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von Asura (Beitrag 1309158)
@Dalai:

Ich dachte mir für jede Property ein Parameter zu nehmen, wo ich den Inhalt eines Editfeldes übermittle ist unschön.
Oder gibt es eine andere Methode?

Ich würde das Objekt erzeugen, dann befüllen und dann der Liste hinzufügen. Wenn man mal die Klasse TEmployee von Sir Rufo als Vorlage nimmt, würdest du ein solches Objekt (statt der Stringliste) erzeugen, dessen Eigenschaften setzen (statt die Strings in die Stringliste zu packen) und das entstandene Objekt in die Liste einfügen (statt die Stringliste zu übergeben). Ich hoffe, die Beschreibung ist auch ohne Code verständlich, momentan hab ich weder Zeit noch Lust (vor allem bei der Wärme), mich auch geistig irgendwie anzustrengen... :stupid:

MfG Dalai

Asura 19. Jul 2015 12:26

AW: Record im Array nutzen? - Sinnvollere Wege?
 
@Dalai:

Ich habe es glaube ich aber trotzdem verstanden. Im Prinzip überspringst du einfach die Parameterübergabe von der einen Unit zur anderen und fügst gleich die Inhalte den Eigenschaften von dem Objekt Employee und fügst das dann der Objektliste zu.

Ich frage mich aber wie ich die Funktion Equals der Klasse TEmployee von Sir Rufo nutzen kann, könnte man mir da eventuell ein Beispiel geben?

Sir Rufo 19. Jul 2015 12:51

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Mit
Delphi-Quellcode:
function TObject.Equals( Obj: TObject ): Boolean;
kann man Instanzen auf Gleichheit prüfen.

Und zwar im Sinne von "stellen das Gleiche dar".

Zwei unterschiedliche Instanzen von
Delphi-Quellcode:
TEmployee
können ja die gleiche ID haben und stellen somit das Gleiche dar.
Delphi-Quellcode:
var e1, e2: TEmployee;

if e1 = e2 then
  ShowMessage( 'Gleiche Instanzen' );
if e1.Equals( e2 ) then
  ShowMessage( 'Gleiche Bedeutung' );

Asura 19. Jul 2015 13:49

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Dankeschön!

Ich habe noch eine weitere Frage:
Wenn ich einen Mitarbeiter hinzufüge über den Button erfolgt nun folgendes:
Ich erstelle ein neues Objekt mit
Delphi-Quellcode:
 Employee.Create();
speichere dann die Inhalte in die Property von Employee und füge das dann der Liste hinzu.

Nun meine Frage ist jz, muss ich mit dem Objekt von TEmployee arbeiten oder muss ich pro Mitarbeiter ein neues Objekt von
Delphi-Quellcode:
TEmployee
erstellen mit einer Index-Nummer (Beispielsweise Employee1, Employee2 usw.) und dieses dann über
Delphi-Quellcode:
Employee1.Create();
initialisieren?

Weil in meiner Methode hätte TObjectlist ja jedes Object in der Liste mit dem Namen "Employee", nur mit verschiedenen Properties oder kann ich das so machen?

mkinzler 19. Jul 2015 13:53

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Eine Instanzvariable ist eine Referenz (Zeiger) auf eine Instanz (Objekt). Du kannt die selbe wiederverwenden oder sogar ganz auf sie verzichten.

Sir Rufo 19. Jul 2015 13:56

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Eine Instanz erzeugt man mit
Delphi-Quellcode:
Employee := TEmployee.Create();
.

Delphi-Quellcode:
Employee.Create();
ruft nur den Konstruktor der Instanz auf, erzeugt aber keine Instanz!

jaenicke 19. Jul 2015 13:58

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von Asura (Beitrag 1309167)
Ich erstelle ein neues Objekt mit
Delphi-Quellcode:
 Employee.Create();

Das ist nicht korrekt. Damit rufst du den Konstruktor des existierenden Objektes Employee auf.
Neu erstellen geht nur mit
Delphi-Quellcode:
 TEmployee.Create();
.

Asura 19. Jul 2015 21:26

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Ohh stimmt, mein Fehler.

Die Frage bleibt aber, ob ich nun die Instanz mit dem gleichen Namen "Employee" nur neu erstellen oder jeweils der neuen Instanz eine Indexnummer angefügt werden soll, weil sonst kann ich doch in der FUnktion Equals keinen Unterschied festlegen, da er nicht weiß, welche Instanz nun überprüft werden soll.

Aber dann frage ich mich, ich muss diese Instanzen ja initialisieren in var:
Delphi-Quellcode:
 var
 Employee1, Employee2: TEmployee
. Wie soll ich da mit einer variablen Indexnummer arbeiten?

Sir Rufo 19. Jul 2015 22:15

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Die Frage verstehe ich nun gar nicht.

Es sei denn, du würdest die ID fälschlicherweise als Indexnummer bezeichnen. Die ID ist aber ein Identifizierer und kein Index. In einer Datenbank würde man es als Primary Index bezeichnen (eindeutiger Hauptindex) oder auch mal als Identity oder Unique Index (eindeutiger Index). Ein einfacher Index kann mehrfach vorkommen und eignet sich nicht als Identifizierer.

Hier sind also die exakten Begrifflichkeiten wichtig, weil die Frage ansonsten von niemandem verstanden wird.

Asura 19. Jul 2015 22:22

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Nun, ich habe ja zwei Möglichkeiten eingetragene Daten in die Objectliste zu speichern:
Entweder ich nutze nur die Instanz Employee von der Klasse TEmployee und lasse sie mir vor dem speichern der Eigenschaften neu erzeugen.

Wie in meinem aktuellen Fall: Methode 1

Delphi-Quellcode:

procedure AddEmployeeData(Index: Integer; EmployeeData: TStringlist);
begin

  F_Main.Employee := TEmployee.Create();

  F_Main.Employee.CardID     := StrtoInt(EmployeeData[0]);
  F_Main.Employee.Prename    := EmployeeData[1];
  F_Main.Employee.Surname    := EmployeeData[2];
  F_Main.Employee.Birthday   := StrtoDate(EmployeeData[3]);
  F_Main.Employee.Workstation := EmployeeData[4];
  F_Main.Employee.Position   := EmployeeData[5];

  F_Main.OLEmployees.Add(F_Main.Employee); // Employee Daten werden als neuer Eintrag gespeichert

  showmessage(TEmployee(F_Main.OLEmployees.Items[0]).Prename); // dient als test
  showmessage(TEmployee(F_Main.OLEmployees.Items[1]).Prename); // dient als Test
end;
Methode 2:

Oder ich müsste für jeden eingetragenen Mitarbeiter beispielsweise eine neue Instanz mit Indexnummer versehen.
Beispiel:
Delphi-Quellcode:
  F_Main.Employee1 := TEmployee.Create(); // Für Mitarbeiter 1 der eingetragen wurde
Delphi-Quellcode:
  F_Main.Employee2 := TEmployee.Create(); // Für Mitarbeiter 2 der eingetragen wurde
Weil bei Equals könnte ich ja dann im Prinzip im zweiten Fall einfach:
Delphi-Quellcode:
if Employee1.Equals( Employee2 ) then
  ShowMessage( 'blablabla' );
machen, welches im ersten Fall ja nicht so einfach geht, da ich ja nur eine Instanz habe, nämlich Employee.

Ich hoffe nun ist das verständlicher.

EDIT: Mit der Index nummer meine ich eig nur die Zahl hinter Employee, also Employee1, Employee2 usw.

Für mich ist Methode 1 einfacher und sie funktioniert auch insoweit, nur Frage ich mich, ob man doch Methode 2 anwenden soll.

Sir Rufo 19. Jul 2015 22:32

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Du kannst die StringList-Orgie komplett weg lassen. Anstatt die Werte aus den Edit-Feldern in eine String-Liste zu schreiben um diese dann von der String-Liste in eine neue
Delphi-Quellcode:
TEmployee
zu schreiben und diese Instanz dann in die Liste,

warum dann nicht gleich die Instanz mit den Werten aus den Edit-Feldern bestücken?

Machst du doch eh schon, nur mit dem Umweg über die String-Liste.

Asura 19. Jul 2015 22:39

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Das mit der TStringliste mache ich nur, weil ich sämtliche Methoden, die zu der Verarbeitung der Instanz Employee zuständig sind, in einer anderen Unit haben wollte. Ich rufe aus der Unit, mit einem Formular, nur die Funktionen auf, die zu der Verarbeitung zuständig sind und es werden hier nur Formatierungsangelegenheiten hinterlegt. Also die Verwaltung der Objektlist findet praktisch nur in der anderen Unit statt.

Ich wollte hier nur die wichtigen "Main-Funktionen" von Formatierung (Wie: Was passiert wenn Edit feld 1 geändert wurde) trennen.

Edit: Achso, ich glaube ich weiß worauf ihr hinaus wollt, das ich selbst in der anderen Unit einfach diese ansprechen kann, oder?

jaenicke 20. Jul 2015 14:07

AW: Record im Array nutzen? - Sinnvollere Wege?
 
Zitat:

Zitat von Asura (Beitrag 1309203)
Edit: Achso, ich glaube ich weiß worauf ihr hinaus wollt, das ich selbst in der anderen Unit einfach diese ansprechen kann, oder?

Richtig, und das hat den Vorteil, dass du nicht wissen musst in welcher Reihenfolge die Parameter in die Liste geschrieben werden müssen.
Du kannst aber auch einfach einen Konstruktor erstellen, der die Parameter bekommt.

In beiden Fällen musst du aber nicht erst in Strings umwandeln.


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