Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi IInterface und TInterfaced Object richtig nutzen (https://www.delphipraxis.net/75602-iinterface-und-tinterfaced-object-richtig-nutzen.html)

Thorus 22. Aug 2006 08:59


IInterface und TInterfaced Object richtig nutzen
 
Hallo,

ich habe mir in Delphi.NET eine Liste selbergeschrieben. Dort hatte ich auch keine Probleme mit Interfacen und die vermischen mit Objecten. Nun brauche ich die gleiche Liste aber in Delphi 32, wo das compilieren nicht fehlerfrei ging. Daher musste ich einiges ändern, aber ein großen Fehler habe ich noch, wo ich keine praktische Lösung weiß. Ich habe schon im Forum gesucht, aber so das richtige noch nicht gefunden.

Der wesentliche Punkte ist, dass ich die Elemente der Liste mit einem Interface verinbart hat. Also es können nur Objekte in die Liste gefügt werden, welche das Interface IElem (selbst gemacht) implementieren.
Ich betrachte jetzt nur eine Methode von IElem, weil es ja nur ums Prinzip geht.

Code:
IElem = interface(IInterface)
  function Equals(e: IElem): Boolean;
end;
TElemStr = class(TInterfacedObject,IElem)
private
  Content: string;
public
  function Equals(e: IElem): Boolean;
end;
...
function TElemStr.Equals(e: IElem): Boolean;
begin
  Result := False;
  if e is TElemStr then
    if (e as TElemStr).Str = Content then
      Result := True;
end;
Die Implementation von Equals funktioniert nur bei .NET.
Das Problem ist, dass ich Interfaces und Objekte nicht einfach so vergleichen kann.
Es ist aber wichtig, dass der Parameter e das Interface IElem implementiert hat. Also e soll ja ein Objekt sein.

Ich hatte probiert, statt e: IElem zu schreiben e: TInterfacedObject, aber das ist auch nicht was ich möchte, weil man ja nicht x-beliebige Objekte übergeben können soll.

Ich hatte versucht so was wie TInterfacedObject zu erstellen, also TInterfacedElem, aber erstens weiß ich nicht so recht wie das geht und zweitens brauch ich ja in der Deklaration von IElem dann den Typ TInterfacedElem als Parameter, welcher das IElem benutzt, was ja nicht geht.

Weiß jemand eine Lösung?

Gruß
Thorus

xaromz 22. Aug 2006 09:47

Re: IInterface und TInterfaced Object richtig nutzen
 
Hallo,

Du musst Deinen Interfaces eine GUID übergeben (mit Strg+Shift+G erstellen). Damit kannst Du Deine Interfaces eindeutig identifizieren:
Delphi-Quellcode:
type
  IElem = interface(IInterface)
  ['{8D4708F4-026A-4CE6-B8EB-5CC20D1FF32A}'] // <- Beispiel-GUID
    function Equals(const e: IInterface): Boolean; // <- Interfaces *IMMER* als const übergeben, spart Referenzzählung
  end;

  TElemStr = class(TInterfacedObject, IElem)
  private
    Content: string;
  public
    function Equals(const e: IInterface): Boolean;
  end;

implementation

uses
  SysUtils;

const
  // Für Vergleich deklarieren
  IID_ELEM: TGUID = '{8D4708F4-026A-4CE6-B8EB-5CC20D1FF32A}';

function TElemStr.Equals(const e: IInterface): Boolean;
begin
  Result := Supports(e, IID_ELEM); // implementiert "e" ein IElem?
end;
Gruß
xaromz

Thorus 22. Aug 2006 10:22

Re: IInterface und TInterfaced Object richtig nutzen
 
Danke,

das mit der GUID hat ich schon mal gelesen, aber nicht recht gewusst was anzufangen.

Danke für den Tipp mit Interfaces als const zu deklarieren.

Wieso kann ich nicht "const e: IElem" statt "const e: IInterface" machen? Spielt das eine Rolle bei dem folgendem Problem?

Ich hatte etwas vergessen, nämlich, im Interface IElem soll es die Funktion "Str" nicht geben, aber bei der Implementation von TElemStr schon.
Jetzt bleibt das Problem, wie ich in der Funktion equals (1. Nachricht) casten kann. Und dann auf die Funktion Str zugreifen kann.

Gruß
Thorus

xaromz 22. Aug 2006 10:48

Re: IInterface und TInterfaced Object richtig nutzen
 
Hallo,
Zitat:

Zitat von Thorus
Wieso kann ich nicht "const e: IElem" statt "const e: IInterface" machen? Spielt das eine Rolle bei dem folgendem Problem?

Das spielt keine Rolle, aber IInterface ist allgemeiner.
Zitat:

Zitat von Thorus
Ich hatte etwas vergessen, nämlich, im Interface IElem soll es die Funktion "Str" nicht geben, aber bei der Implementation von TElemStr schon.

Ist doch kein Problem.
Zitat:

Zitat von Thorus
Jetzt bleibt das Problem, wie ich in der Funktion equals (1. Nachricht) casten kann. Und dann auf die Funktion Str zugreifen kann.

Soll das heißen, Du willst über das Interface auf das Objekt zugreifen? Dann kannst Du sowas machen:
Delphi-Quellcode:
type
  IElem = interface(IInterface)
  ['{8D4708F4-026A-4CE6-B8EB-5CC20D1FF32A}'] // <- Beispiel-GUID
    function Equals(const e: IInterface): Boolean; // <- Interfaces *IMMER* als const übergeben, spart Referenzzählung
    function GetSelf: TObject; // <- Gibt das eigentliche Objekt zurück
  end;

  TElemStr = class(TInterfacedObject, IElem)
  private
    Content: string;
  public
    function Equals(const e: IInterface): Boolean;
    function GetSelf: TObject;
  end;

implementation

uses
  SysUtils;

const
  // Für Vergleich deklarieren
  IID_ELEM: TGUID = '{8D4708F4-026A-4CE6-B8EB-5CC20D1FF32A}';

function TElemStr.Equals(const e: IInterface): Boolean;
begin
  Result := Supports(e, IID_ELEM); // implementiert "e" ein IElem?

  // Aufruf der Objektfunktion:
  if Result then
    TElemStr(e as IElem).GetSelf).Str := 'xyz';
end;

function TElemStr.GetSelf: TObject;
begin
  Result := Self;
end;
Gruß
xaromz

Thorus 22. Aug 2006 11:42

Re: IInterface und TInterfaced Object richtig nutzen
 
Nochmals Danke!

Ich habe es gleich eingebaut und probiert und es funktionier genau so wie es soll. (Waren zwar paar kleine Tippfehler in deinem Code, aber nicht schlimm)

Die Idee mit dem GetSelf ist wirklich hilfreich.

Gruß
Thorus


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