Unterschiedliche Objekte in einer Liste speichern
Hallo,
ich versuche mich gerade an einer Liste die unterschiedliche Objekte enthalten soll. Zur bessern Erklärung habe ich ein einfaches Beispiel erstellt. Das Ziel ist ein Objekt zu erhalten welches eine Liste enthält die unterschiedliche Objekte verwalten kann. Dieses Objekt ist vom Typ "TItems" und enthält eine TObjectList in der Objekte vom Typ "ItemA" oder "ItemB" gespeichert werden können. Ich stehe gerade auf dem Schlauch und weiß nicht was ich machen muss damit es funktioniert oder ob ich bereits bei dem ganzen Ansatz falsch liege.
Delphi-Quellcode:
Jedoch klappt das nicht und beim Versuch eines der Objekte in die Liste zu speichern erhalte ich nur eine Fehlermeldung "Ungültige Zeigeroperation"
unit Unit1;
interface uses Classes, Contnrs; type TField = class(TObject) private FName: String; FValue: String; public constructor Create; destructor Destroy; override; property Name: String read FName write FName; property Value: String read FValue write FValue; end;{TField} TFields = class(TObject) private FInnerList: TList; function GetItem(Index: Integer): TField; procedure SetItem(Index: Integer; Item: TField); function GetCount: Integer; public constructor Create; destructor Destroy; override; function Add(Item: TField): Integer; procedure Clear; procedure Delete(Index: Integer); property Count: Integer read GetCount; property Items[Index: Integer]: TField read GetItem write SetItem; end;{TFields} TItemA = class(TObject) private FName: String; FDesc: String; FFields: TFields; public constructor Create; destructor Destroy; override; property Name: String read FName write FName; property Desc: String read FDesc write FDesc; property Fields: TFields read FFields write FFields; end;{TItemA} TItemB = class(TObject) private FName: String; FComment: String; FText: String; FFields: TFields; FComp: TFields; public constructor Create; destructor Destroy; override; property Name: String read FName write FName; property Comment: String read FComment write FComment; property Text: String read FText write FText; property Fields: TFields read FFields write FFields; property Comp: TFields read FComp write FComp; end;{TItemB} TItems = class(TObject) private FInnerList: TObjectList; function GetData(Index: Integer): TObject; procedure SetData(Index: Integer; Data: TObject); function GetDataCount: Integer; public constructor Create; destructor Destroy; override; function Add(Data: TObject): Integer; procedure Clear; procedure Delete(Index: Integer); property Count: Integer read GetDataCount; property Items[Index: Integer]: TObject read GetData write SetData; end;{TItems} implementation uses SysUtils; { TField } constructor TField.Create; begin inherited; //init FName := EmptyStr; FValue := EmptyStr; end; destructor TField.Destroy; begin //deinit FValue := EmptyStr; FName := EmptyStr; inherited; end; { TFields } function TFields.Add(Item: TField): Integer; begin result := FInnerList.Add(Item); end; procedure TFields.Clear; var Idx: Integer; begin //deinit if Assigned(FInnerList) and (FInnerList.Count > 0) then begin for Idx := 0 to FInnerList.Count - 1 do begin TObject(FInnerList.Items[Idx]).Free; end;{for} end;{if} FInnerList.Clear; end; constructor TFields.Create; begin inherited; //init FInnerList := TList.Create; end; procedure TFields.Delete(Index: Integer); begin //Objekt freigeben TObject(FInnerList.Items[Index]).Free; //Eintrag löschen FInnerList.Delete(Index); end; destructor TFields.Destroy; var Idx: Integer; begin //deinit if Assigned(FInnerList) and (FInnerList.Count > 0) then begin for Idx := 0 to FInnerList.Count - 1 do begin TObject(FInnerList.Items[Idx]).Free; end;{for} end;{if} FInnerList.Free; inherited; end; function TFields.GetCount: Integer; begin result := FInnerList.Count; end; function TFields.GetItem(Index: Integer): TField; begin result := FInnerList.Items[Index]; end; procedure TFields.SetItem(Index: Integer; Item: TField); begin if Assigned(Item) then FInnerList.Items[Index] := Item; end; { TItems } function TItems.Add(Data: TObject): Integer; begin result := FInnerList.Add(Data); end; procedure TItems.Clear; var Idx: Integer; begin //deinit if Assigned(FInnerList) and (FInnerList.Count > 0) then begin for Idx := 0 to FInnerList.Count - 1 do begin TObject(FInnerList.Items[Idx]).Free; end;{for} end;{if} FInnerList.Clear; end; constructor TItems.Create; begin inherited; //init FInnerList := TObjectList.Create; end; procedure TItems.Delete(Index: Integer); begin //Objekt freigeben TObject(FInnerList.Items[Index]).Free; //Eintrag löschen FInnerList.Delete(Index); end; destructor TItems.Destroy; var Idx: Integer; begin //deinit if Assigned(FInnerList) and (FInnerList.Count > 0) then begin for Idx := 0 to FInnerList.Count - 1 do begin TObject(FInnerList.Items[Idx]).Free; end;{for} end;{if} FInnerList.Free; inherited; end; function TItems.GetData(Index: Integer): TObject; begin result := FInnerList.Items[Index]; end; function TItems.GetDataCount: Integer; begin result := FInnerList.Count; end; procedure TItems.SetData(Index: Integer; Data: TObject); begin if Assigned(Data) then FInnerList.Items[Index] := Data; end; { TItemA } constructor TItemA.Create; begin inherited; //init FName := EmptyStr; FDesc := EmptyStr; FFields := TFields.Create; end; destructor TItemA.Destroy; begin //deinit FFields.Free; FDesc := EmptyStr; FName := EmptyStr; inherited; end; { TItemB } constructor TItemB.Create; begin inherited; //init FName := EmptyStr; FComment := EmptyStr; FText := EmptyStr; FFields := TFields.Create; FComp := TFields.Create; end; destructor TItemB.Destroy; begin //deinit FComp.Free; FFields.Free; FText := EmptyStr; FComment := EmptyStr; FName := EmptyStr; inherited; end; end.
Delphi-Quellcode:
procedure TForm17.Button1Click(Sender: TObject);
var Items: TItems; ItemA: TItemA; ItemB: TItemB; Field: TField; Idx: Integer; Comp: TField; begin Items := TITems.Create; try //'Item A' erzeugen ItemA := TItemA.Create; ItemA.Name := 'test'; ItemA.Desc := 'bla'; for Idx := 1 to 10 do begin Field := TField.Create; Field.Name := 'Feld'+IntToStr(Idx); Field.Value := IntToStr(Idx); ItemA.Fields.Add(Field); end;{for} //'Item A' der Liste hinzufügen Items.Add(ItemA); //<- Ungültige Zeigeroperation //'Item B' erzeugen ItemB := TItemB.Create; ItemB.Name := 'BBB'; ItemB.Comment := 'Zweiter Objekt-Typ'; ItemB.Text := 'Bla Bla Mr. Freeman'; for Idx := 1 to 10 do begin Field := TField.Create; Field.Name := 'Feld'+IntToStr(Idx); Field.Value := IntToStr(Idx); ItemB.Fields.Add(Field); end; for Idx := 1 to 5 do begin Comp := TField.Create; Comp.Name := 'Comp'+IntToStr(Idx); Comp.Value := IntToStr(Idx); ItemB.Comp.Add(Comp); end; //'Item B' der Liste hinzufügen Items.Add(ItemB); finally Items.Free; end;{try..finally} end; |
AW: Unterschiedliche Objekte in einer Liste speichern
Hast du denn mal debugged?
Wo genau krachts denn im TItems.Add? Ist die Liste erstellt? Wird der constructor von TItems (korrekt) ausgeführt? Was mir noch aufgefallen ist: In TItems.Delete brauchst du folgende Zeile nicht (bzw. sie kann sogar Fehler verursachen):
Delphi-Quellcode:
TObject(FInnerList.Items[Index]).Free;
Eine TObjectList gibt die Objekte die entfernt werden automatisch vorher frei. (Das wird durch die "OwnsObjects" Eigenschaft gesteuert, die auch im constructor optional übergeben werden kann) |
AW: Unterschiedliche Objekte in einer Liste speichern
Warum nimmst Du TList und nicht TObjectList?
|
AW: Unterschiedliche Objekte in einer Liste speichern
Zitat:
Delphi-Quellcode:
... und das verursacht das Problem. Denn er gibt die Instanz frei und die
TObjectList
Delphi-Quellcode:
will die Instanz auch noch freigeben.
TObjectList
Rumms! :stupid: |
AW: Unterschiedliche Objekte in einer Liste speichern
Zitat:
|
AW: Unterschiedliche Objekte in einer Liste speichern
Zitat:
|
AW: Unterschiedliche Objekte in einer Liste speichern
Hallo,
was passiert, wenn du nur das hier machst?
Delphi-Quellcode:
ItemA := TItemA.Create;
Items.Add(ItemA); //<- Ungültige Zeigeroperation Übrigens hat TObjectList ein OwnsObject (Boolean), setze das auf False, dann kannst du das Free auch selbst machen. Heiko |
AW: Unterschiedliche Objekte in einer Liste speichern
Zitat:
Delphi-Quellcode:
und spart sich jede Menge Boilerplate-Code :stupid:
true
|
AW: Unterschiedliche Objekte in einer Liste speichern
Guten Morgen,
ihr hattet alle recht es lag daran das ich in der Klasse in der ich TObjectList verwendet habe dieses selbst freigeben wollte und als das Objekt sich selbst freigeben wollte knallte es. Ich stand da wohl irgendwie auf dem Schlauch, aber jetzt scheint alles zu funktionieren. Noch mal vielen Dank euch allen und einen schönen Tag. ;-) |
AW: Unterschiedliche Objekte in einer Liste speichern
Auch bei OwnsObjects=True kann man Free selber machen. :roll:
TObjectList.Delete <> TObjectList.Remove |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:05 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