Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit Interfaces (https://www.delphipraxis.net/74402-problem-mit-interfaces.html)

hoika 2. Aug 2006 18:02


Problem mit Interfaces
 
Hallo,

ich verzweifle gerade an Interfaces.

Das Problem ist die Stelle // XXX //
Danach wird der Speicher der lokalen Varaible TestId überschrieben.

Ich denke, der Fehler liegt im GetInterface.
Nur wie soll ich denn sonst ein Interface auf die Klasse bekommen ???.


Unteres Bsp führt zum Überschreiben der lokalen Variabel TestCode.
Was mache ich falsch ?

Ich will von dieser Basisklasse weg,
also bitte keine "pack das property doch in die Basisklasse"

Danke
Heiko

Delphi-Quellcode:
type
  IResource = interface
    function GetResType: Integer;

    property iResType: Integer
      read GetResType
  end;

type
  TBaseRes = class(TInterfacedClass)
    function GetInterface: IResource; virtual; abstract;
  end;

// Res1

type
  TRes1 = class(TBaseRes, IRes)
    function GetInterface: IResource; override;
    function GetResType: Integer;
  end;

function TRes1.GetInterface: IResource;
var
  IntRes: IResource;
begin
  IntRes:= Self;
  Result:= IntRes;
end;

function TRes1.GetResType: Integer;
begin
  Result:= 1;
end;

// Res2

type
  TRes2 = class(TBaseRes, IRes)
    function GetInterface: IResource; override;
    function GetResType: Integer;
  end;

function TRes2.GetInterface: IResource;
var
  IntRes: IResource;
begin
  IntRes:= Self;
  Result:= IntRes;
end;

function TRes2.GetResType: Integer;
begin
  Result:= 2;
end;

// problem code

var
  iResItem : Integer;
  ResItem : TBaseRes;
  IntRes  : IResource;
  TestId  : Integer;
begin
  TestId:= 100;

  for iResItem:= 0 to ResList.Count-1 do
  begin
    ResItem:= ResList[iResItem];

    IntRes:= ResItem.GetInterface;


  // XXX //
    if IntRes.iResType=1 do
    begin
      blaaa


   // TestId wurde verändert !!
  end;

xaromz 2. Aug 2006 21:40

Re: Problem mit Interfaces
 
Hallo,
Zitat:

Zitat von hoika
Ich denke, der Fehler liegt im GetInterface.
Nur wie soll ich denn sonst ein Interface auf die Klasse bekommen ???.

Ich weiß jetzt nicht, wie intensiv Du Dich mit Interfaces beschäftigt, hast, aber da Interfaces in Delphi kein Sprachfeature sind, sondern COM-Interfaces, bekommst Du arge Probleme, wenn Du Interfaces und normale Klassen mischst.
Zitat:

Zitat von hoika
Unteres Bsp führt zum Überschreiben der lokalen Variabel TestCode.
Was mache ich falsch ?

Ich kann im geposteten Code keine Ursache für dieses Problem finden, aber ein paar Stolperfallen (siehe ersten Kommentar).
Zitat:

Zitat von hoika
Ich will von dieser Basisklasse weg,
also bitte keine "pack das property doch in die Basisklasse"

Dann schmeiß doch die Basisklasse weg. Wozu brauchst Du die?

Hier noch ein kleiner Link zu meinem Interface-Tutorial (ich poste das immer wieder gerne :mrgreen: ).

Gruß
xaromz

jbg 2. Aug 2006 22:11

Re: Problem mit Interfaces
 
Zitat:

Zitat von xaromz
aber da Interfaces in Delphi kein Sprachfeature sind, sondern COM-Interfaces

Was willst du damit sagen? Interfaces sind sehr wohl ein Sprachfeature von Delphi (C++ kennt keine Interfaces im aktuellen Standard, da werden abstrakte Klasse dafür "misbraucht"). Es kommt nur darauf an, was das dahintersteckende Objekt bei _AddRef und _Release Aufrufen macht. Hat man z.B. TInterfacedPersistent oder gar TComponent als Implementor-Basisklasse, kann man sehr wohl Interfaces und Objektreferenzen mischen. Man muss halt bei Interfaces wissen, was so im Hintergrund abläuft.

hoika 3. Aug 2006 06:55

Re: Problem mit Interfaces
 
Hallo,

Das Problem beim Ersetzen ist ...

viiiiiieeeell Code. ;(


Es war ja nur als Bsp. gedacht.
Die dahinterliegenden Klassen sind "etwas" größer,
so ein paar tausend Zeilen müssen geändert und
vor allem getestet werden.

Ich will die nach und nach umstellen.
Dafür ist das GetInterface da.
Das <iResType> property war das erste, was ich umstellen wollte.
Das hatte ich in 3 Stunden erledigt.
Und dann kommt es jetzt zu diesem Speicherfehler.

Ich werde mir mal das Tutorial ansehen .

Mein Frage zielte ja darauf hin,
ob in dem Code ein prinzipieller Fehler ist.

Heiko

Bernhard Geyer 3. Aug 2006 07:20

Re: Problem mit Interfaces
 
Zitat:

Zitat von hoika
Mein Frage zielte ja darauf hin,
ob in dem Code ein prinzipieller Fehler ist.

Ich verstehe nicht wieso du eine gesonderte GetInterface-Methode benötigst und du nicht einfach mittels is und as auf dieses Interface zugreifst?
Auch ist das Mischen von Klassen und Interfacezugriffen problematisch. Hier gibt es eine Fall bei Delphi wo die automatische Referenzzählung durcheinander kommt und das Objekt schon freigegeben wird. Und dies ist vermutlich bei deiner GetInterface-Methode mit der lokalen Variable der Fall.

hoika 3. Aug 2006 07:51

Re: Problem mit Interfaces
 
Hallo Bernhard,

meinst du

Delphi-Quellcode:
var
  iResItem : Integer;
  ResItem : TBaseRes;
  Res_1    : TRes1;
  IntRes  : IResource;
  TestId  : Integer;
begin
  TestId:= 100;

  for iResItem:= 0 to ResList.Count-1 do
  begin
    ResItem:= ResList[iResItem];

    if ResItem is TRes1 then
    begin
      Res_1:= ResList[iResItem];
    end;
??

Darauf bin ich ja noch gar nicht gekommen ...

Nach dem Lesen des Tutorials (speziell das Mischen von Klassen und Interfaces)
habe ich aber den alten Stand wieder ausgecheckt.


Ich wollte 3 völlig verschiedenen Klassen (Person,Arbeitsplatz,Fahrzeug)
mehrere neue gemeinsame Eigenschaften (Resourcentyp, Ressourcenname) zuordnen,
ohne sie von einer einzelnen Basisklasse abzuleiten.
Alle 3 Klassen haben aber selber schon ne Menge eigener Properties.
Deshalb dachte ich, Interfaces wären eine gute Idee.
Alle "Ressourcen" wurden dann in eine TList geladen und
über das gemeinsame Interface zugreifen.

Das war der Plan ..


Heiko

xaromz 3. Aug 2006 09:08

Re: Problem mit Interfaces
 
Hallo,
Zitat:

Zitat von jbg
Was willst du damit sagen? Interfaces sind sehr wohl ein Sprachfeature von Delphi (C++ kennt keine Interfaces im aktuellen Standard, da werden abstrakte Klasse dafür "misbraucht"). Es kommt nur darauf an, was das dahintersteckende Objekt bei _AddRef und _Release Aufrufen macht. Hat man z.B. TInterfacedPersistent oder gar TComponent als Implementor-Basisklasse, kann man sehr wohl Interfaces und Objektreferenzen mischen. Man muss halt bei Interfaces wissen, was so im Hintergrund abläuft.

Damit will ich sagen, dass man eben nicht Klassen und Interfaces mischen kann, weil das so in Delphi nicht geplant war. Interfaces wurden "angebaut", anstatt sie richtig zu integrieren. Deshalb haben auch Interfaces eine Referenzzählung und Klassen nicht. Wenn man weiß, wie man damit umgeht, ist das kein Problem. Leider erledigt das aber eben nicht die Sprache (bzw. der Compiler) für Dich, sondern Du musst es selbst erledigen.
Schau Dir mal .Net an. Da kannst Du immer Klassen und Interfaces mischen, weil das in allen Sprachen von Anfang an so vorgesehen war (die Referenzzählung ist ja sowieso für den GC notwendig).

Gruß
xaromz

hoika 3. Aug 2006 09:42

Re: Problem mit Interfaces
 
Hallo,

gerade aus .Net hatte ich die Überlegung.
In einem Artikel des .net Magazins stand das mal drin.

Was mich stört ist, dass die Klasse zerstört wird,
wenn der Referenzzeiger 0 ist.

Naja, man sollte halt neue Sachen an einfachen Testprogrammem
ausprobieren. Ich hatte das gleich eingebaut ...


Heiko

Bernhard Geyer 3. Aug 2006 09:46

Re: Problem mit Interfaces
 
Zitat:

Zitat von xaromz
Damit will ich sagen, dass man eben nicht Klassen und Interfaces mischen kann, weil das so in Delphi nicht geplant war. Interfaces wurden "angebaut", anstatt sie richtig zu integrieren. Deshalb haben auch Interfaces eine Referenzzählung und Klassen nicht. Wenn man weiß, wie man damit umgeht, ist das kein Problem. Leider erledigt das aber eben nicht die Sprache (bzw. der Compiler) für Dich, sondern Du musst es selbst erledigen.

In 99,9% der Fälle brauchst Du dich bei Interfaces nicht um die Referenzzählung kümmern da dies der Compile automatisch macht.

Zitat:

Zitat von xaromz
Schau Dir mal .Net an. Da kannst Du immer Klassen und Interfaces mischen, weil das in allen Sprachen von Anfang an so vorgesehen war (die Referenzzählung ist ja sowieso für den GC notwendig).

Garbage Collection hat nicht unbedingt was mit Referenzzählung zu tun. Dies sind 2 paar Stiefel. Richtig ist das man bei einer Sprache mit GC sowohl bei Klassen(referenzen) und Interfaces sich nicht mehr um die freigabe kümmern muss.
GC über Referenzzählung ist nur eine möglicher Algorithmus für die Speicherfreigabe.

xaromz 3. Aug 2006 09:59

Re: Problem mit Interfaces
 
Hallo,
Zitat:

Zitat von Bernhard Geyer
In 99,9% der Fälle brauchst Du dich bei Interfaces nicht um die Referenzzählung kümmern da dies der Compile automatisch macht.

Es ging hier um das Mischen von Objekten und Interfaces. Da muss man sich schon kümmern.
Zitat:

Zitat von Bernhard Geyer
Garbage Collection hat nicht unbedingt was mit Referenzzählung zu tun. Dies sind 2 paar Stiefel. Richtig ist das man bei einer Sprache mit GC sowohl bei Klassen(referenzen) und Interfaces sich nicht mehr um die freigabe kümmern muss.
GC über Referenzzählung ist nur eine möglicher Algorithmus für die Speicherfreigabe.

Ich weiß, es ging mir auch eher darum, dass eben die Referenzzählung (oder was auch immer in .Net gemacht wird) der Interfaces nicht losgelöst vom eigentlichen Objekt funktioniert, sondern der selbe Mechanisums auch beim Objekt greift. Deshalb kann es auch nicht passieren, dass man sich ein Interface holt und dann automatisch das Objekt freigegeben wird, obwohl das nicht gewünscht war.

Gruß
xaromz


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