Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Interface und 'normale' Referenz (https://www.delphipraxis.net/154317-interface-und-normale-referenz.html)

hansmaad 6. Sep 2010 13:29

Delphi-Version: 2010

Interface und 'normale' Referenz
 
Hallo zusammen,
folgendes Problem. Ich möchte ein Konzept über ein Interface definieren.
Delphi-Quellcode:
type
    IMachtBuh = interface
        procedure Buh;
    end;
Implementiert wird das z.B. von
Delphi-Quellcode:
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;
So, schön. Solche Objekt können jetzt Buh machen.
Delphi-Quellcode:
procedure MachBuh(b : IMachtBuh);
begin
    b.Buh;
end;
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.
Delphi-Quellcode:
var
    f : Foo;
begin
    f := Foo.Create;
    MachBuh(f);
    /// ...
    f.WasAnderes; // haha, denkste! f is futsch.
    FreeAndNil(f);
end.
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:
Delphi-Quellcode:
var
    f : Foo;
    dummy : IMachtBuh;
begin
    f := Foo.Create;
    dummy := f;
    MachBuh(f);
    /// ...
    f.WasAnderes;
end.
Was aber auch nicht besonders elegant ist. Oder ich lass mir von Euch erklären wie man es am besten macht.:wink:

Bernhard Geyer 6. Sep 2010 13:34

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!

Uwe Raabe 6. Sep 2010 14:25

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.

hansmaad 6. Sep 2010 14:48

AW: Interface und 'normale' Referenz
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1047788)
Kombinierte Verwendung von Interface + Objektreferenz macht Probleme mit automatisher Referenzzählung.
Wenn du mit Interfaces arbeitest dann nur noch mit diesen!

Das Problem hab ich ja schon erkannt. Die Frage ist wie es zu lösen ist. Ein IWasAnders Interface einführen? Aber wie sieht dann Foos Erzeugung aus?
Zitat:

Zitat von Uwe Raabe (Beitrag 1047795)
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.

Ursprünglich hatte ich mich ja über die Referenzzählung bei Interfaces gefreut. Für so Fälle wo das stört klingt das aber interessant, wobei der Name ...Persistent irgendwie verwirrt. Muss ich mir mal anschauen.

Bernhard Geyer 6. Sep 2010 15:01

AW: Interface und 'normale' Referenz
 
Zitat:

Zitat von hansmaad (Beitrag 1047800)
Das Problem hab ich ja schon erkannt. Die Frage ist wie es zu lösen ist. Ein IWasAnders Interface einführen? Aber wie sieht dann Foos Erzeugung aus?

erzeugung ist genauso. Du darfst es halt keinen Referenzzeiger mehr zuweisen:

Delphi-Quellcode:
var
    f : IMachtBuh;
begin
    f := Foo.Create;
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:

Delphi-Quellcode:
funktion CoFoo: IMachtBuh;
begin
  result = Foo.Create;
end;

hansmaad 6. Sep 2010 15:19

AW: Interface und 'normale' Referenz
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1047801)
erzeugung ist genauso. Du darfst es halt keinen Referenzzeiger mehr zuweisen:

Delphi-Quellcode:
var
    f : IMachtBuh;
begin
    f := Foo.Create;

Ja nu ruf aber mal Foo.WasAnderes auf.

quantum 6. Sep 2010 15:58

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;

xaromz 6. Sep 2010 16:15

AW: Interface und 'normale' Referenz
 
Hallo,

wenn es nur darum geht, eine Funktion aufzurufen, kannst Du auch mit
Delphi-Quellcode:
const
arbeiten:
Delphi-Quellcode:
procedure MachBuh(const b : IMachtBuh);
begin
    b.Buh;
end;
Dadurch wird der Referenzzähler beim Aufruf nicht verändert und folglich das Objekt am Ende nicht freigegeben. Man sollte übrigens immer
Delphi-Quellcode:
const
verwenden, das vermeidet Fehler und ist außerdem noch schneller.

Gruß
xaromz

Bernhard Geyer 6. Sep 2010 17:55

AW: Interface und 'normale' Referenz
 
Zitat:

Zitat von quantum (Beitrag 1047827)
Seit Delphi 2010 kann man endlich von Interface auf Instanz casten.

Das halte ich für nicht sinnvoll. Man verwendet ja Interfaces um von den Objektinstanz-Klassen wissen zu müssen.

Bernhard Geyer 6. Sep 2010 17:56

AW: Interface und 'normale' Referenz
 
Zitat:

Zitat von xaromz (Beitrag 1047834)
Dadurch wird der Referenzzähler beim Aufruf nicht verändert und folglich das Objekt am Ende nicht freigegeben.

Guter Tipp :thumb: Sonst mach ich bei Strings/Records alles immer mit const. Aber das das bei Interfaces auch was positives bewirkt ist ja schön.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr.
Seite 1 von 2  1 2      

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