![]() |
Delphi-Version: 2010
Interface und 'normale' Referenz
Hallo zusammen,
folgendes Problem. Ich möchte ein Konzept über ein Interface definieren.
Delphi-Quellcode:
Implementiert wird das z.B. von
type
IMachtBuh = interface procedure Buh; end;
Delphi-Quellcode:
So, schön. Solche Objekt können jetzt Buh machen.
type
Foo = class(TInterfacedObject, IMachtBuh) public procedure Buh; procedure WasAnderes; end; procedure Foo.Buh; begin WriteLn('Foo Buh'); end; procedure Foo.WasAnderes; begin WriteLn('Was anderes'); end;
Delphi-Quellcode:
Das Problem ist jetzt, dass eine Foo Referenz im Aufruf von MachBuh implizit in ein IMachtBuh konvertiert wird, dass die Instanz am Ende von MachBuh auffrisst.
procedure MachBuh(b : IMachtBuh);
begin b.Buh; end;
Delphi-Quellcode:
Natürlich kann ich f als IMachtBuh deklarieren, dann hab ich aber keinen Zugriff mehr auf die Konzepte die Foo selber defineirt oder über andere Interfaces erbt. Oder ich mach sowas:
var
f : Foo; begin f := Foo.Create; MachBuh(f); /// ... f.WasAnderes; // haha, denkste! f is futsch. FreeAndNil(f); end.
Delphi-Quellcode:
Was aber auch nicht besonders elegant ist. Oder ich lass mir von Euch erklären wie man es am besten macht.:wink:
var
f : Foo; dummy : IMachtBuh; begin f := Foo.Create; dummy := f; MachBuh(f); /// ... f.WasAnderes; end. |
AW: Interface und 'normale' Referenz
Kombinierte Verwendung von Interface + Objektreferenz macht Probleme mit automatisher Referenzzählung.
Wenn du mit Interfaces arbeitest dann nur noch mit diesen! |
AW: Interface und 'normale' Referenz
Wenn du weißt, was du tust, kannst du statt von TInterfacedObject auch von TInterfacedPersistent (classes.pas) ableiten. Dann musst du aber selbst auch für die Freigabe sorgen.
|
AW: Interface und 'normale' Referenz
Zitat:
Zitat:
|
AW: Interface und 'normale' Referenz
Zitat:
Delphi-Quellcode:
Hier nehm ich mir of COM als vorbild und leg mit eine Co-Funktion an und die Implementierende Klasse soweit verstecken das keiner mehr darauf kommt diese entsprechend über Refernzzeiger zu verwenden:
var
f : IMachtBuh; begin f := Foo.Create;
Delphi-Quellcode:
funktion CoFoo: IMachtBuh;
begin result = Foo.Create; end; |
AW: Interface und 'normale' Referenz
Zitat:
|
AW: Interface und 'normale' Referenz
Seit Delphi 2010 kann man endlich von Interface auf Instanz casten.
Code:
var
f : IMachtBuh; begin f := Foo.Create; (f as Foo).WasAnderes; |
AW: Interface und 'normale' Referenz
Hallo,
wenn es nur darum geht, eine Funktion aufzurufen, kannst Du auch mit
Delphi-Quellcode:
arbeiten:
const
Delphi-Quellcode:
Dadurch wird der Referenzzähler beim Aufruf nicht verändert und folglich das Objekt am Ende nicht freigegeben. Man sollte übrigens immer
procedure MachBuh(const b : IMachtBuh);
begin b.Buh; end;
Delphi-Quellcode:
verwenden, das vermeidet Fehler und ist außerdem noch schneller.
const
Gruß xaromz |
AW: Interface und 'normale' Referenz
Zitat:
|
AW: Interface und 'normale' Referenz
Zitat:
|
AW: Interface und 'normale' Referenz
Zitat:
Da gebe ich dir Recht. Mir selbst ist das suspekt. Besser ein Interface für die benötigten Methoden einführen und nichts anderes als die Interfaces benutzen.
Delphi-Quellcode:
IMachtWasAnderes = interface
procedure WasAnderes; end; Foo = class(TInterfacedObject, IMachtBuh, IMachtWasAnderes) |
AW: Interface und 'normale' Referenz
Zitat:
Zitat:
|
AW: Interface und 'normale' Referenz
Zitat:
Es gibt noch weitere Varianten der Referenzzählung (zum Beispiel bei der TRemotable für Soap). Interfaces in Delphi erlauben Freiheiten bei der Implementierung, die es in anderen Sprachen nicht gibt - wer mag, kann das natürlich auch als Vorteil sehen. |
AW: Interface und 'normale' Referenz
Notfalls erzeugt man sich eine eigene Klasse, die das gewünschte verhalten hat.
|
AW: Interface und 'normale' Referenz
Zitat:
|
AW: Interface und 'normale' Referenz
Hallo,
Zitat:
Delphi-Quellcode:
Gruß
type
IIntf = interface procedure Blubb; end; TIntf = class(TInterfacedObject, IIntf) procedure Blubb; end; procedure bla; var A: IIntf; begin A := TIntf.Create; // Referenz 1 Machwas(A); // keine Änderung end; // hier Referenz 0 -> Objekt wird zerstört procedure Machwas(const B: IInf) // Keine Änderung begin B.Blubb; // hier kann jeder Thread etwas mit dem Interface machen, der Referenzzähler bleibt immer >= 1 end; xaromz |
AW: Interface und 'normale' Referenz
Zitat:
Delphi-Quellcode:
Ist das richtig?
procedure Machwas(const B: IInf);
procedure MachwasNichtConst(B: IInf); procedure bla; var A: IIntf; begin A := TIntf.Create; // Referenz 1 StartThread(Machwas(A)); // keine Änderung end; // hier Referenz 0 -> Objekt wird zerstört. MachWas() hat Pech gehabt. procedure blaAnders; var A: IIntf; begin A := TIntf.Create; // Referenz 1 StartThread(MachwasNichtConst(A)); // Referenz 2 end; // hier Referenz 1 -> Objekt wird nicht zerstört. MachWasNichtConst() hat Glück gehabt. Ich kanns leider nicht mal eben ausprobieren, weil ich in Delphi noch überhaupt keine Ahnung von threads habe. War nur schonmal vorweg gefragt. |
AW: Interface und 'normale' Referenz
Hallo,
Zitat:
Gruß xaromz |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:55 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