Announcement

Collapse
No announcement yet.

interfaces

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • interfaces

    Hallo liebe Leute,

    Wie kann man feststellen, ob eine Klasse die Co-Klasse eines Interfaces ist und auf die Interface-Prozeduren zugreifen?
    Beispiel:

    type
    IKannwas = interface
    procudure MachWas;
    end;

    TFormKannWas = class(TForm,IKannWas)
    public
    procedure MachWas;
    end;

    TFormKannAuchWas = class(TForm,IKannWas)
    public
    procedure MachWas;
    end;

    Dieses Interface ist nur dann sinnvoll einzusetzen, wenn
    ich nun auch eine beliebiges TForm abfragen kann, ob es
    eine Co-Klasse dieses Interfaces ist,
    aber so funkioniert das nicht:

    prodedure FormMachtWas(F: TForm);
    begin
    //was nicht geht wie ich es sonst machen würde:
    if F is IKannWas then IKannWas(F).MachWas
    end;

    kann mir jemand helfen?

    Gruß Uwe

  • #2
    Hallo!

    IMyinterface = interface
    ['{8581A00A-6192-44A5-83C5-7F1997E055B7}']
    procedure Foo;
    end;

    TMyObject = class ( TInterfacedobject, IMyINterface)
    procedure Foo;
    end;
    procedure TMyObject.Foo;
    begin
    showmessage ( 'Hello world!' );
    end;

    procedure TForm1.ButtonClick(Sender: TObject);
    var
    help: TMyObject;
    helpI: IMyINterface;
    begin
    help := TMyObject.create;
    help.queryinterface ( IMyInterface, helpi );
    if helpi = nil then begin
    showmessage ( 'Falsch!' );
    end
    else begin
    helpi.Foo;
    end;
    end;

    QueryInterface ist das Zauberwort.
    Du solltest aber nach Möglichkeit als Vorfahr TInterfacedObject verwenden, da sind die benötigten Methoden schon mit drin.
    Die GUID im Interface ist PFLICHT! Die kannst Du mit Strg+Shift+G erzeugen (glaube ich), da ich mit den Modelmaker Tools arbeite habe ich das schon lange nicht mehr "von Hand" machen müssen.

    Alternativ musst Du die Methoden selbst einbinden:
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    function TDBManager.QueryInterface(const IID: TGUID; out Obj): HResult;
    const
    E_NOINTERFACE = HResult($80004002);
    begin
    if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
    end;

    function TDBManager._AddRef: Integer;
    begin
    Result := -1;
    end;

    function TDBManager._Release: Integer;
    begin
    Result := -1;
    end;

    Das entspricht einer Realisierung ohne Zählung der Referenzen.

    BYE BERN

    Comment


    • #3
      Nochmal ich.

      Nachdem ich gesehen habe wie chaotisch der Source aussieht hier das gepackte Projekt

      Comment


      • #4
        Hallo Bernd,
        danke für das Beispielprogramm.
        Soweit ist alles klar.
        Aber wie kommst Du auf die TGUID
        ['{8581A00A-6192-44A5-83C5-7F1997E055B7}'] ?
        Ist das völlig beliebig, oder was muß man da beachten?

        Außerdem habe ich den Verdacht, daß der Aufruf von QueryInterface viel mehr Rechenzeit beansprucht als
        z.B. "if objekt is ..". Oder liege ich da falsch?

        Gruß Uw

        Comment


        • #5
          Das Zauberwort heisst "Supports".
          Die Funktion gibt an, ob ein Objekt oder eine Schnittstelle eine bestimmte Schnittstelle unterstützt. Um festzustellen, ob die Schnittstelle unterstützt wird, ruft Supports die Methode QueryInterface der bereitgestellten Schnittstelle (oder die Schnittstelle des bereitgestellten Objekts) auf.

          Einfach mal in der Hilfe nachschauen.

          Sicherlich wird der Aufruf von QueryInterface viel mehr Rechenzeit beanspruchen als z.B. "if objekt is ..". Aber nur so funktionierts sicher

          Comment


          • #6
            Hallo Bernd,
            danke für deinen Kommentar.
            Die Funktion "supports" ist mir bekannt, aber auch da brauche ich eine TGUID; ich weiß aber nicht, was die einzutragenden Hex-Ziffern bedeuten und welche ich da verwenden kann/darf ??
            Gruß Uw

            Comment


            • #7
              Hallo Uwe,

              Einfach in Supports den Interface-Bezeichner einsetzen, um den Rest kümmert sich Delphi.

              z.B.
              if Supports(TFormKannWas, IKannWas) then
              (TFormKannWas as IKanWas).MachWas;

              Vorraussetzung ist ein interface mit gültiger GUID. Die GUID muss immer mit angegeben werden und sollte immer eindeutig sein. Um sicher zu gehen, lass Dir eine mit Strg+Shift+G von Delphi erzeugen.
              Ich habe mich noch nie um diese Hex-Ziffern gekümmert, alles Delphi machen lassen und es passt.
              Gruss Bern

              Comment


              • #8
                Hallo Bernd,
                danke für den Hinweis.
                Das mit dem Strg+Shift+G habe ich nicht gewußt bzw mir war nicht klar, daß ich mich dann um den Inhalt der TGUID nicht mehr kümmern muß.
                Weil mir die TGUID's suspekt waren, habe ich bisher mit drei verschiedenen eigenen Verfahren gearbeitet, die so etwas wie Mehrfachvererbung implementieren, eines der drei Verfahren ist Interfaces sehr ähnlich.
                Es könnte sein, daß diese Verfahren schneller sind als das (von mir gemutmaßte) Suchen einer TGUID innerhalb der Funktion "supports".
                Ich wollte ein Zip mit Beispielprogramm als Anhang beifügen, aber das Hinzufügen von Anhängen klappt bei mir nicht (habe den Sysop deshalb kontaktiert) und sobald das geht, werde ich das nachholen.
                Gruß
                Uw

                Comment

                Working...
                X