Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi interfaces: Ein paar grundlegende Fragen (zB. woher die AV?) (https://www.delphipraxis.net/87507-interfaces-ein-paar-grundlegende-fragen-zb-woher-die-av.html)

yankee 1. Mär 2007 16:21


interfaces: Ein paar grundlegende Fragen (zB. woher die AV?)
 
Hi @ll,

alles, was ich an Erfahrung mit Interfaces habe kommt von Java und jetzt probiere ich diese mal in Delphi anzuwenden und .... habe damit ein paar Probleme ;-).

Ich habe mir überlegt eine allgemeine Lösung zum sortieren einer TObjectList zu coden:
Delphi-Quellcode:
unit USortedList;

interface

uses SysUtils, Contnrs;

type

  IComparable =interface
    ['{210AC03E-6716-49A5-8B54-34845AE4A087}']
    function Compare(other: TObject):integer;
  end;
   TSortedList =class(TObjectList)
     public
       function Add(neu: IComparable):integer;
       procedure Sort;
   end;

   TIntTest =class(TInterfacedObject, IComparable)
     public
       v: integer;
       function Compare(other: TObject):integer;
   end;

implementation

function TIntTest.Compare(other: TObject):integer;
begin
  result :=v-TIntTest(other).v;
end;

function TSortedList.Add(neu: IComparable):integer;
begin
  result :=inherited Add(TObject(neu));
end;

procedure TSortedList.Sort;
 procedure QuickSort(iLo, iHi: Integer);
 var
   Lo, Hi: Integer;
   Mid: IComparable;
 begin
   Lo := iLo;
   Hi := iHi;
   Supports(Items[(Lo + Hi) div 2],IComparable,Mid); //Hier gibt es eine AV
   repeat
     while Mid.Compare(Items[Lo]) < 0 do Inc(Lo);
     while Mid.Compare(Items[Hi]) > 0 do Dec(Hi);
     if Lo <= Hi then
     begin
       Exchange(Lo,Hi);
       Inc(Lo);
       Dec(Hi);
     end;
   until Lo > Hi;
   if Hi > iLo then QuickSort(iLo, Hi);
   if Lo < iHi then QuickSort(Lo, iHi);
 end;
begin
  QuickSort(0,Count-1);
end;

end.
Dazu habe ich folgende Fragen:
1. Wofür ist die id (['{210AC03E-6716-49A5-8B54-34845AE4A087}']) gut? Soweit ich das sehe ist die 100% zufällig.
2.
Delphi-Quellcode:
TIntTest =class(TInterfacedObject, IComparable)
Muss ich das Objekt unbedingt von TInterfacedObject ableiten? Da wäre dann ja schon 80% der Grundidee von interfaces futsch...?! Ich will ja, dass ich meine Klasse, die ich später in der Liste mal speichere möglicherweise von was anderem ableiten.
3.
Delphi-Quellcode:
Supports(Items[(Lo + Hi) div 2],IComparable,Mid);
Am Anfang habe ich versucht das Objekt einfach zu casten (IComparable(Items[...])) aber wie ich gelesen habe funktioniert das nur in .net uind nicht in D für win32. Aber Supports funktioniert auch nicht so, wie ich gedacht hätte, denn der Aufruf wirft mir eine Access Violation. Warum? Und vorallem: Wie mache ich es richtig?

Kedariodakon 1. Mär 2007 16:37

Re: interfaces: Ein paar grundlegende Fragen (zB. woher die
 
Zitat:

Zitat von yankee
1. Wofür ist die id (['{210AC03E-6716-49A5-8B54-34845AE4A087}']) gut? Soweit ich das sehe ist die 100% zufällig.

die GUID ist mehr oder minder zufällig berechnet, die benötigst du um z.b. mit As zu arbeiten...
Die ist vor allem auch dann wichtig, wenn du mit dem Interface auch außerhalb von deiner Anwendung arbeiten willst, ich glaub ohne GUID geht dann nichts mehr...

Zitat:

Zitat von yankee
2.
Delphi-Quellcode:
TIntTest =class(TInterfacedObject, IComparable)
Muss ich das Objekt unbedingt von TInterfacedObject ableiten? Da wäre dann ja schon 80% der Grundidee von interfaces futsch...?! Ich will ja, dass ich meine Klasse, die ich später in der Liste mal speichere möglicherweise von was anderem ableiten.

Nein musst du nicht, du musst nur die Methoden von TInterface in deiner Klasse implementieren...
Wenn du es nicht machst, meckert Delphi...

Zitat:

Zitat von yankee
3.
Delphi-Quellcode:
Supports(Items[(Lo + Hi) div 2],IComparable,Mid);
Am Anfang habe ich versucht das Objekt einfach zu casten (IComparable(Items[...])) aber wie ich gelesen habe funktioniert das nur in .net uind nicht in D für win32. Aber Supports funktioniert auch nicht so, wie ich gedacht hätte, denn der Aufruf wirft mir eine Access Violation. Warum? Und vorallem: Wie mache ich es richtig?

Das Problem wird sein, dass deine Objekte der Reihe nach freigegeben werden (glaub ich)...

Mit jedem neuen Methoden-Aufruf von Supports wird in Mid ein neues Interface von dem entsprechenden Objekt angefordert, und immer wenn dann Mid neu belegt wird, wird das Objekt von welchem das Interface vorher war wieder freigegeben, da der RefZähler dann jedesmal auf 0 gehen sollte...

Zumindest tip ich mal darauf...


Nie Interfaces mit Objekten mischen, sonst gibts fast immer => :firejump:

Bye Christian

bttb930 1. Mär 2007 16:39

Re: interfaces: Ein paar grundlegende Fragen (zB. woher die
 
Ich glaube wenn Du unter Delphi mit Interfaces arbeiten willst, dann ist es hilfreich, deine Java-Erfahrungen komplett zu vergessen. Interfaces in Java sind ein mächtiges Tool, unter Delphi eher kaum zu gebrauchen. Klar, manchmal habe ich auch schon welche benutzt, aber wenn das Problem irgendwie auch anders zu lösen ist, dann mach ich's lieber anders. In Java und C# benutze ich dagegen so oft es geht Interfaces.

xaromz 1. Mär 2007 16:47

Re: interfaces: Ein paar grundlegende Fragen (zB. woher die
 
Hallo,

dass Du eine AV bekommst, wird daran liegen, dass Du ein Interface nach TObject castest und dieses speicherst. Dabei wird der Referenzzähler nicht erhöht (weak reference). Deshalb wird das Interface vermutlich irgendwann freigegeben, und wenn Du dann irgendwann darauf zugreifen willst...

//Edit:
Warum benutzt Du eigentlich eine TObjectList, und keine TInterfaceList?

Gruß
xaromz

yankee 1. Mär 2007 16:59

Re: interfaces: Ein paar grundlegende Fragen (zB. woher die
 
Zitat:

Zitat von Kedariodakon
Das Problem wird sein, dass deine Objekte der Reihe nach freigegeben werden (glaub ich)...

Mit jedem neuen Methoden-Aufruf von Supports wird in Mid ein neues Interface von dem entsprechenden Objekt angefordert, und immer wenn dann Mid neu belegt wird, wird das Objekt von welchem das Interface vorher war wieder freigegeben, da der RefZähler dann jedesmal auf 0 gehen sollte...

Ich bin mir nicht sicher, ob ich dich jetzt richtig verstanden habe (ich galube ich habe das garnichtm, weil ich nicht wiess, was ein RefZähler ist) aber Die AV kommt schon beim ersten Aufruf von Supports (ich bin da mal durchgesteppt. Und schaffe es nicht den Befehl auch nur einmal erfolgreich auszuführen).

@bttb930: Ich werde es mir merken, abe zumindest für dieses Problem fällt mri keine bessere Lösung ein.

@xaromz: *gerde deinen Beitrag bemerk*:
RefZöähler = der vom Garbagecollector? Ihr seit euch schin im klaren, dass ich mit D2k5 for Win32 und nicht for .net arbeite? Da gibt es doch keinen GC, oder?

Und ich verwende die TObjectList, weil ich auch die Referenzen zu den Objekten gerne hätte um diese Freen zu können, wenn ich ein Objekt in der Liste lösche...
Ich habe es übrigens auch mal probiert ohne die Add-M;ethode zu überschreiben. Ich ahbe Add eigentlich nur überschrieben um die Möglichkeit auszuschliessen Objekte in die Liste einzufügen, die IComparable nicht implementieren...

xaromz 1. Mär 2007 19:50

Re: interfaces: Ein paar grundlegende Fragen (zB. woher die
 
Hallo,
Zitat:

Zitat von yankee
@xaromz: *gerde deinen Beitrag bemerk*:
RefZöähler = der vom Garbagecollector? Ihr seit euch schin im klaren, dass ich mit D2k5 for Win32 und nicht for .net arbeite? Da gibt es doch keinen GC, oder?

Mir ist vor Allem klar, dass Interfaces unter Win32 einer Referenzzählung unterworfen sind :wink: . Deshalb ja auch die beiden Methoden _AddRef und _Release.
Zitat:

Zitat von yankee
Und ich verwende die TObjectList, weil ich auch die Referenzen zu den Objekten gerne hätte um diese Freen zu können, wenn ich ein Objekt in der Liste lösche...
Ich habe es übrigens auch mal probiert ohne die Add-M;ethode zu überschreiben. Ich ahbe Add eigentlich nur überschrieben um die Möglichkeit auszuschliessen Objekte in die Liste einzufügen, die IComparable nicht implementieren...

Das kannst Du vergessen. Ein Interface besitzt keine Free-Methode. Aber da hier eben die Referenzzählung greift, hast Du auch kein Problem.

Gruß
xaromz


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