Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Ableiten von Interfaces (https://www.delphipraxis.net/80249-ableiten-von-interfaces.html)

paresy 5. Nov 2006 20:26


Ableiten von Interfaces
 
Anbei ein kleines Beispiel was mir zu schaffen macht...

Was ich wollte:
Ein Interface welches die Grundlegenden Funktionen anbietet
Mehrere Interfaces die davon abgeleitet werden, die speziellere Funktionen haben und dann implementiert werden in den entsprechendnen Klassen

Das Problem ist aber, dass Delphi mir aber nicht mehr erlaubt auf das erste Interface zu casten, sondern eine "Interface not Supported" Exception wirft, obwohl das Interface welches implementiert wurde, ja von dem auf das ich casten will abgeleitet wurde.

Wenn ich die Klasse so gestalte:
Delphi-Quellcode:
 TObject2 = class(TInterfacedObject, IInterface1, IInterface2)
Dann klappt alles... nur erschließt sich mir nicht, wieso das andere falsch ist.

Danke für eure Antworten.

paresy


VCL Applikation mit Button drauf
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
 IInterface1 = interface(IUnknown)
 ['{72523EAC-6949-48A8-B3BC-4B795472A85B}']
  procedure Foo;
 end;

 IInterface2 = interface(IInterface1)
 ['{04197A80-7EFF-460C-BB53-322C276233CF}']
  procedure Bar;
 end;

 TObject2 = class(TInterfacedObject, IInterface2)
  public
   procedure Foo;
   procedure Bar;
 end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TObject2.Foo;
begin
 //
end;

procedure TObject2.Bar;
begin
 //
end;

procedure TForm1.Button1Click(Sender: TObject);
var obj: IUnknown;
begin

 obj := TObject2.Create() as IUnknown;

 (obj as IInterface1).Foo; //Interface not Supported

end;

end.

Elvis 5. Nov 2006 20:32

Re: Ableiten von Interfaces
 
Wenn ich mich recht entsinne war das um irgendeiner COM-Gemeinheit Tribut zu zollen.

Du kannst die instanz problemlos als dein interface benutzen (also einer Referenz vom Typ deines Interfaces zuweisem).
Der as-Operator wird bei Interaces im Hintergrund QueryInterface ausführen und genau hier scheint der Hund begraben zu sein. Die GUID für das Interface ist nur dann mit deiner Klasse verknüpt (oder andersrum), wenn du es explizit angibst.
Innerhalb von Delphi macht das keinen Unterschied. Oftmals brauchst du nicht einmal GUIDs. Aber wehe du musst Supports oder QueryInterface (also auch "as") benutzen.

paresy 28. Feb 2007 01:01

Re: Ableiten von Interfaces
 
Was übrigens noch schön wäre, aber anscheinend nicht geht, ist das mehrfache Ableiten von Interfaces:

Delphi-Quellcode:
type
  IFoo = interface
     procedure Hello;
     procedure Walk;
  end;

  IBar = interface
     procedure Hello;
     procedure Talk;
  end;

  ICombo = interface(IFoo, IBar)
     procedure ChewBubbleGum;
  end;
paresy

Sidorion 28. Feb 2007 09:13

Re: Ableiten von Interfaces
 
Wozu IFoo und IBar? Diese Interfaces sind identisch.... Interfaces müssen nicht mehrfach vererben, das macht dann die Klasse.
Delphi-Quellcode:
  TCombo=Class(TObject, IFoo, IBar)
Wobei Du hier Schwierigkeiten bekommst, da die Interfaces identische Methoden haben. Hier musst Du bei der Klassendefinition erklären, welche Methode der Klasse welche Methode welchen Interfaces implementiert.
Imho liegt hier ein Verständnisproblem vor: ein Interface verpflichtet eine Klasse zur Implementierung bestimmter Methoden. Wenn die Methoden beider Interfaces identisch sind, sind die Interfaces identisch und somit unnötig, ein weiteres zu definieren.

Der_Unwissende 28. Feb 2007 09:37

Re: Ableiten von Interfaces
 
Zitat:

Zitat von Sidorion
Wozu IFoo und IBar? Diese Interfaces sind identisch....

Hi,
Walk und Talk sind schon zwei verschiedene Dinge. Das zwei Methoden gleich heißen hat doch zudem nichts mit identisch zu tun. Immerhin kann es sein, dass zwei Entwickler, die nichts miteinander zu tun haben, jeweils ein Interface mit einer bestimmten Methode entwickeln. Ein Dritter möchte dann beide in seinem Projekt verwenden und könnte jetzt auch denken dass die Identisch sind, dumm nur wenn Instanzen dieser Interfaces verwendet werden sollen (da kommt dann die GUID ins Spiel), dann wird man spätestens merken, dass die nicht identisch waren.

Man sollte sich eher gegenteilig nie von gleichen Namen täuschen lassen.


Zitat:

Zitat von paresy
Was übrigens noch schön wäre, aber anscheinend nicht geht, ist das mehrfache Ableiten von Interfaces

Mehrfachvererbung wäre ja auch für Klassen von Zeit zu Zeit wünschenswert, wird aber (aus gutem Grund) von sehr wenigen Sprachen erlaubt. In Delphi sind die Interfaces eigentlich COM-Interfaces (wie ja schon erwähnt wurde). Beim Entwurf des Component Object Modells musste man sich natürlich auch ein paar Gedanken machen und hat sich (wie in anderen Sprachen) gegen die Mehrfachvererbung entschieden.
Es gibt glaube ich einige Diskussionen zu den Vor- und Nachteilen von Mehrfachvererbung. Wie gesagt unterstützen die meisten (bekannten?) Sprachen das nicht, C++ ist da die bekannteste Ausnahme.

Gruß Der Unwissende

Kedariodakon 28. Feb 2007 15:43

Re: Ableiten von Interfaces
 
Zitat:

Zitat von paresy
Was übrigens noch schön wäre, aber anscheinend nicht geht, ist das mehrfache Ableiten von Interfaces:

Delphi-Quellcode:
type
  IFoo = interface
     procedure Hello;
     procedure Walk;
  end;

  IBar = interface
     procedure Hello;
     procedure Talk;
  end;

  ICombo = interface(IFoo, IBar)
     procedure ChewBubbleGum;
  end;
paresy

Im gewissen Sinne wieder unsinnig, da man dann nicht mehr über IFoo und IBar zugreifen könnte... (Hast du ja schon mitbekommen)

Aber so könntest du auch sowas realisieren:
Delphi-Quellcode:
Type
  IFoo = Interface
    ['{65E88BD5-D440-4C1C-AE03-6EBC59A18772}']
    Procedure Hello;
    Procedure Walk;
  End;

  IBar = Interface
    ['{F77C17B1-2DE4-459F-B06E-F6BF3BBD2EB7}']
    Procedure Hello;
    Procedure Talk;
  End;
 
  ICombo = interface
    ['{CB36309F-5C44-49EE-91DB-408D50E311BD}']
    Procedure ChewBubbleGum;
  End;

  TObj = Class( TInterfacedObject, IFoo, IBar, ICombo )
  Private                  
    { Private-Deklaration } 
  Protected
    { Protected-Deklaration }
    Procedure IFoo.Hello = fHello;
    Procedure Walk;  
    Procedure IBar.Hello = bHello;
    Procedure Talk;
    Procedure ChewBubbleGum;
    Procedure fHello;
    Procedure bHello;
  Public                    
    { Public-Deklaration }
  End;
Sprich, je nach Interface-Zugriff eine entsprechende Methode... ;)

Bye Christian

paresy 28. Feb 2007 16:00

Re: Ableiten von Interfaces
 
Ja. Ich könnte es so implementieren. (Das Beispiel oben war auch etwas überspitzt gewählt)

Sowas würde ja im simplen Falle reichen. Damit könnte ich IBoth nach außen zeigen und man würde auf A und B zugreifen können ohne jeweils das Object nach IFoo oder IBar casten zu müssen.
Delphi-Quellcode:
type
  IFoo = interface
     procedure A;
  end;

  IBar = interface
     procedure B;
  end;

  IBoth = interface(IFoo, IBar);

  TBothClass = class(TInterfacedObject, IBoth)
   ...
  end;
Da ich meinen Plugin Entwicklern aber nur die Interfaces zur Verfügung stellen will, und nicht meine ganze Implementation, wäre es natürlich schön gewesen ein Interface zu haben, welches beschreibt, welche Interfaces die Klasse implementiert. :)

paresy


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