Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Object ersetzen aber trotzdem behalten (https://www.delphipraxis.net/116381-object-ersetzen-aber-trotzdem-behalten.html)

Yheeky 27. Jun 2008 17:37


Object ersetzen aber trotzdem behalten
 
Hi,

ich hab mal wieder ne Frage bezüglich TObject und TObjectList ;-)
Angenommen ich habe folgende TObjectList:
Delphi-Quellcode:
begin
   auto1 := TAuto.Create;
   auto1.Marke := 'Opel';
   auto1.Modell := 'Astra';
   autoSammlung.Add(auto1);
   
   autoSammlung[0].Marke = 'Opel';
   autoSammlung[0].Modell = 'Astra';
   autoSammlung[1].Marke = 'VW';
   autoSammlung[1].Modell = 'Golf';
   autoSammlung[2].Marke = 'Audi';
   autoSammlung[2].Modell = 'TT';
end;
Ich möchte nun Item[1] durch einen neuen Eintrag ersetzen, ihn aber dennoch als Objekt behalten. Wie kann ich das anstellen?

mkinzler 27. Jun 2008 17:40

Re: Object ersetzen aber trotzdem behalten
 
Durch Ersetzten in der Liste bleibt das Objekt bestehen, man kann aber nur darauf zugreifen, wenn man eine Referenz darauf irgendwie speichert

Yellow579 27. Jun 2008 17:42

Re: Object ersetzen aber trotzdem behalten
 
Hallo mkinzler!

Diese Aussage von dir stimmt nur, wenn die TObjectList Instanz mit false im Constructor angelegt wurde oder OwnsObjects auf false gesetzt wurde.

In allen anderen Fällen würde die an der Position vorhandene Instanz freigegeben werden. Dabei ist es unerheblich ob nil oder eine Instanz zugewiesen wird.

Gruss
Yellow

mkinzler 27. Jun 2008 17:45

Re: Object ersetzen aber trotzdem behalten
 
Durch Ersetzen würden sie auch dann nicht zerstört

Cyf 27. Jun 2008 17:45

Re: Object ersetzen aber trotzdem behalten
 
Ein Beispiel daür wäre (wenn ich das richtig verstehe) folgendes.

Delphi-Quellcode:
var aAuto: TAuto

aAuto:= TAuto(autoSammlung[1]);
Dann hast du deine Referenz in aAuto, ob der Cast notwendig, kann ich so grad nicht sagen, weil ich nicht weiß was deine Liste genau ist.

Im Übrigen musst du ein Objekt ehe du alle Referenzen darauf verlierst erst freigeben, ansonsten führt dich zu Memory-Leaks.

Delphi-Quellcode:
aAuto.Free
[Edit]Falls die Liste ihre Kombonenten nicht besitzt und automatisch freigibt, aber dann kannst du entweder eine Kopie der Instanz anlegen, oder dies in der Regel irgendwo deaktivieren.

Yellow579 27. Jun 2008 17:49

Re: Object ersetzen aber trotzdem behalten
 
Hallo mkinzler!

Zitat:

Zitat von mkinzler
Durch Ersetzen würden sie auch dann nicht zerstört

Doch. Die TObjectList führt in der SetItems Methode entsprechend ein Notify Aufruf mit lnDeleted aus und das führt zur Freigabe des alten Elementes an der Position, so lange das vorherige Item nicht nil war.

Das alte Objekt wird in jedem Falle zerstört - wenn OwnsObjects auf true steht.

Gruss
Yellow

Missionar 27. Jun 2008 17:54

Re: Object ersetzen aber trotzdem behalten
 
Zitat:

Zitat von Yellow579
Hallo mkinzler!

Zitat:

Zitat von mkinzler
Durch Ersetzen würden sie auch dann nicht zerstört

Doch. Die TObjectList führt in der SetItems Methode entsprechend ein Notify Aufruf mit lnDeleted aus und das führt zur Freigabe des alten Elementes an der Position, so lange das vorherige Item nicht nil war.

Das alte Objekt wird in jedem Falle zerstört - wenn OwnsObjects auf true steht.

Gruss
Yellow

Quatsch RTFM

MKinzler hat recht!

Yheeky 27. Jun 2008 18:29

Re: Object ersetzen aber trotzdem behalten
 
Mhmm naja...verstehe ich noch nicht ganz:
Wie mache ich das denn bei folgender Unit (habe mal schnell eine vergleichbare zusammengeschrieben):

Delphi-Quellcode:
unit Unit1;

interface

uses
  Contnrs, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TAuto = class(TObject)
   Marke, Modell : String;
  end;

type TAutoSammlung = class (TObjectList)
end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    autosammlung : TAutoSammlung;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var newcar, oldcar : TAuto;
begin
  oldCar := TAuto(autosammlung[1]);

  newCar := TAuto.Create;
  newCar.Marke := 'Porsche';
  newCar.Modell := 'Boxter';
  autoSammlung[1] := newCar;

  ShowMessage(oldCar.Marke + #13 + oldCar.Modell);

end;

procedure TForm1.FormCreate(Sender: TObject);
var auto1 : Tauto;
begin
   autoSammlung := TAutoSammlung.Create;

   auto1 := TAuto.Create;
   auto1.Marke := 'Opel';
   auto1.Modell := 'Astra';
   autoSammlung.Add(auto1);
   auto1 := TAuto.Create;
   auto1.Marke := 'VW';
   auto1.Modell := 'Golf';
   autoSammlung.Add(auto1);
   auto1 := TAuto.Create;
   auto1.Marke := 'Audi';
   auto1.Modell := 'TT';
   autoSammlung.Add(auto1);
end;

end.
oldCar wird überschrieben, obwohl ich autoSammlung[1] eigentlich vorher newCar zugewiesen habe...hoffe jetzt könnte ihr mich eher nachvollziehen.

Missionar 27. Jun 2008 19:13

Re: Object ersetzen aber trotzdem behalten
 
@Yellow579: hast recht :oops:

Hawkeye219 27. Jun 2008 19:43

Re: Object ersetzen aber trotzdem behalten
 
Hallo Yheeky,

mit der Methode Delphi-Referenz durchsuchenTObjectList.Extract kannst du ein Element aus einer Objektliste entfernen ohne es freizugeben. Alle folgenden Listenelemente rücken automatisch auf und schließen somit die entstehende Lücke. Ein neues Element lässt sich natürlich jederzeit mit Hilfe der Methode Delphi-Referenz durchsuchenTObjectList.Insert an einer beliebigen Position der Liste einfügen. Bei der Verwendung von Extract musst du beachten, dass du auch die Verantwortung für die Freigabe des entfernten Elements übernimmst.

Noch ein Vorschlag: spendiere deiner Klasse TAuto einen eigenen Konstruktor, damit vereinfachst du das Erstellen neuer Instanzen:

Delphi-Quellcode:
var
  Auto : TAuto;
begin
  Auto := TAuto.Create('Opel', 'Astra');
  [..]
Gruß Hawkeye

Cyf 27. Jun 2008 20:49

Re: Object ersetzen aber trotzdem behalten
 
Zwei weitere gut gemeinte Vorschläge die ich mal so in den Raum werf:

1. Benutz für einen Zeilenumbruch besser #13#10 oder die Konstante sLineBreak.
2. Weiß ja nicht ob das dein Richtiger Autotyp ist, aber falls, besitzt er keine Methoden und von daher ist es besser hier einen Record (unten auf der Seite) zu benutzen.

Yheeky 28. Jun 2008 12:37

Re: Object ersetzen aber trotzdem behalten
 
Zitat:

Zitat von Hawkeye219
Hallo Yheeky,

mit der Methode Delphi-Referenz durchsuchenTObjectList.Extract kannst du ein Element aus einer Objektliste entfernen ohne es freizugeben. Alle folgenden Listenelemente rücken automatisch auf und schließen somit die entstehende Lücke. Ein neues Element lässt sich natürlich jederzeit mit Hilfe der Methode Delphi-Referenz durchsuchenTObjectList.Insert an einer beliebigen Position der Liste einfügen. Bei der Verwendung von Extract musst du beachten, dass du auch die Verantwortung für die Freigabe des entfernten Elements übernimmst.

Noch ein Vorschlag: spendiere deiner Klasse TAuto einen eigenen Konstruktor, damit vereinfachst du das Erstellen neuer Instanzen:

Hallo Hawneye219, danke, cool! Wusste garnicht, dass es eine extra Funktion dafür gibt, aber auf einem anderen Wege habe ich es auch nicht hinbekommen ;-)
Was meinst du genau mit, dass ich die Verantwortung für die Freigabe des Elementes übernehmen muss?
EDIT: Vergiss es, hab´s verstanden ;-) Du meintest ja, dass das Objekt nicht freigegeben wird und dass ich mich da drum kümmern muss ist klar. Aber das ist ja gerade meine Absicht, dass das Objekt dann nicht freigegeben wird :-)

Ein Konstruktor vereinfacht das Ganze, da hast du recht - danke auch hierfür!

Cyf 28. Jun 2008 12:51

Re: Object ersetzen aber trotzdem behalten
 
Du musst das Objekt, ehe du die letzte Referenz (Pointer) auf es verlierst mittels
Delphi-Quellcode:
TObject.Free
freigeben, da sonst der Speicher den es belegt, nicht wieder an da Systetm zurückgegeben wird, sondern im Nirvana verschwindet, bis sich nach Pogrammbeendigung das Betriebssystem (hoffentlich) darum kümmert, dass er wieder befreit wird, worauf man sich aber nicht verlassen kann, da dies sehr systemabhängig und unzuverlässig ist, der Speicher während der Ausführung verloren geht und es absolut schlechter Programmierstil wäre.


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