![]() |
Delphi-Version: 5
Instanz Klasse einfach weg
Hallo,
im Beitrag ![]() An das Problem mit Mischung von Objekt- und Interface-Referenz hatte ich zuerst gedacht. Das war es aber nciht. Die Ursache für mein Problem ist mit inzwischen bekannt und hat mehrere Ursachen. Hier ein Beispiel - extremst vereinfacht:
Delphi-Quellcode:
Soweit der hoffentlich sinnvolle Auszug.
TBlub = class (TInterfacedObject, IBlub1, IBlub2);
//Irgend wo steht dann var blub : IBlub1; begin blub := TBlub.Create() as IBlub1; ... end; //weiter: procedure TBlub.Initialize(); //override var blbl: IBlub2; begin blb := Self as IBlub2; //Hier erhöht sich der Referenzzähler Self.Egal := irgeeinservice.CreateEtwas(blbl); blbl := Nil; //Hier erniedrigt sich der Referenzzähler end; procedure TBlub.AfterConstruction();//override begin // Call AfterConstruction of base class inherited; //Da drin geht der Referenzzähler auf 0 // Initialize member of descendant class self.Initialize(); //... end; Ich finde es an sich ja schon logisch, dass man in AfterConstruction zuerst inherited aufruft und dann erst das eigene macht. 1. Problem (meinte der Kollege): Warum macht man so viel Dinge im Konstruktor. Der sollte schlank bleiben. 2. Ein Hack in der RTL den ich für nicht so dolle finde:
Delphi-Quellcode:
Mein Problem habe ich nun gelöst, indem ich das mein Ding nicht mehr im Konstruktor mache sondern später erst.
procedure TInterfacedObject.AfterConstruction;
begin // Release the constructor's implicit refcount AtomicDecrement(FRefCount); end; // Set an implicit refcount so that refcounting during construction won't destroy the object. class function TInterfacedObject.NewInstance: TObject; begin Result := inherited NewInstance; TInterfacedObject(Result).FRefCount := 1; end; Aber: Wie hat sich der Erfinder das gedacht? |
AW: Instanz Klasse einfach weg
Ja, das ist so.
Du kannst das wie folgt umgehen:
Delphi-Quellcode:
oder alternativ
//weiter:
procedure TBlub.Initialize(); //override begin DoInitialize(Self); end; procedure TBlub.DoInitialize(const blb: IBlub2); begin Self.Egal := irgeeinservice.CreateEtwas(blbl); end;
Delphi-Quellcode:
Was dein Kollege meint ist schon richtig, du machst es aber nicht richtiger, wenn du den Code nur in anderen Methoden verlagerst und diese trotzdem im Rahmen des Konstruktors ausführst. Dadurch wird der Konstruktor der Klasse selber nicht schlanker, denn der Code wird ja trotzdem ausgeführt. Es ist einfach nur Augenwischerei.
//weiter:
procedure TBlub.Initialize(); //override var blbl: IBlub2; begin blb := Self as IBlub2; //Hier erhöht sich der Referenzzähler Self.Egal := irgeeinservice.CreateEtwas(blbl); blbl := Nil; //Hier erniedrigt sich der Referenzzähler end; procedure TBlub.AfterConstruction();//override begin // Call AfterConstruction of base class inherited; //Da drin geht der Referenzzähler auf 0 // Initialize member of descendant class //self.Initialize(); //... end; constructor TBlub.Create; begin inherited; Self.Initialize(); end; |
AW: Instanz Klasse einfach weg
Zitat:
Er hat vermutlich nicht damit gerechnet, daß jemand das AfterConstruction überschreibt und darin außerhalb dieser Klammer (also nach dem inherited) mit dem Interface rumhantiert. Übrigens: Für das Destroy gibt es so eine Sicherung interessanterweise nicht. Hantieren mit Interfaces innerhalb des Destroy eines TInterfacedObject ist also ebenfalls zum Scheitern verurteilt. Deswegen arbeite ich in der Regel mit einer eigenen Ableitung, die lediglich das BeforeDestruction ergänzt und den RefCount auf 1 setzt:
Delphi-Quellcode:
begin
inherited; FRefCount := 1; end; Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:25 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 by Thomas Breitkreuz