Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Sinn und Zweck von Interfaces (https://www.delphipraxis.net/126230-sinn-und-zweck-von-interfaces.html)

Ares 20. Dez 2008 12:59


Sinn und Zweck von Interfaces
 
Hallo!

Ich beschäftige mich gerade erstmalig tiefer mit COM und hier spielen Interfaces ja eine entscheidende Rolle. Allerdings verstehe ich den Sinn und Zweck dahinter nicht so ganz.

Bislang hatte ich eigentlich eine recht klare Vorstellung davon was ein Interface ist und wofür man es braucht. Bei den Tutorials zu COM ist das Ganze aber ins Schwanken geraten. Am Besten erkläre ich erstmal was ich unter einem Interface verstehe und wenn ich Blödsinn erzähle könnt ihr mich gerne korrigieren.


Was ich bislang unter einem Interface verstehe:
Ein Interface definiert eine Schnittstelle, also eine Menge von Methoden. Hierbei wird nur gesagt welche Methoden es gibt und wie diese aussehen (Name und Signatur), nicht aber wie diese implementiert sind. In dieser Hinsicht ist ein Interface nichts anderes als eine abstrakte Klasse: In beiden Fällen werden Methoden definiert aber nicht implementiert. Einziger Unterschied ist, dass ein Interface ausschließlich Definitionen enthält, während eine in einer abstrakten Klassen neben abstrakten Methoden durchaus auch konkrete vorhanden sein können.

Interfaces sind also ein Zusicherung, dass eine Klasse die ein Interface implementiert bestimmte Methoden anbietet. Interfaces sind notwendig, weil es in Delphi keine Mehrfachvererbung gibt. Andernfalls könnte man auch nur mit abstrakten Klassen arbeiten.

Was bei COM anders ist
Soweit ich das Verstanden habe muss jedes Interface mit einer GUID versehen und von IUnknown abgeleitet werden. Die GUID ist notwendig, damit ein Interface eindeutig identifiziert und im System registriert werden kann. IUnknown ist das "Oberinterface" aller anderen Interfaces. Hier wird die Implementierung für die Referenzzählung, etc. gefordert.


Habe ich das soweit richtig beschrieben? Dann ergeben sich für mich ein paar Fragen die ich mir nicht beantworten kann:

Wofür brauche ich die die GUID und IUnknown bei der "normalen" Programmierung?
Den Sinn und Zweck den diese Teile bei COM verwenden habe ich durchaus verstanden, aber was ist wenn ich gar kein COM verwende sondern mir ein Interface einfach nur eine Schnittstelle zusichern soll? Wozu brauche ich dann eine GUID? Wozu brauche ich dann einen Referenzzähler? Gibt es bei Delphi gar keine "normalen" Interfaces die nur für die "normale" Programmierung genutzt werden und nicht für COM?

Wozu sind Interface-Objekte notwendig?
In mehreren Tutorials werden Interfaces quasi als Objekte verwendet. Hier ein Beispiel:

Delphi-Quellcode:
type
  IMyInterface = interface
    ['{6675C5C0-D95C-11D4-BDE0-00A024BAF736}']
    procedure DisplaySomething;
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
    procedure DisplaySomething;
  end;

  TMyForm = class(TForm)
    TestBtn: TButton;
    procedure TestBtnClick(Sender: TObject);
  end;

var
  MyForm: TMyForm;

implementation

{$R *.DFM}
procedure TMyForm.TestBtnClick(Sender: TObject);
var
  MyClass : TMyClass;            
  MyInterface : IMyInterface;    
begin
  // Warum erstellt man ein "Interface Objekt"?
  MyInterface := TMyClass.Create;
  MyInterface.DisplaySomething;  

  // Warum erstellt man nicht direkt ein "echtes" Objekt und benutzt das?
  MyClass := TMyClass.Create;
  MyClass.DisplaySomething;
end;
Welchen Sinn/Vorteil/Nutzen/Zweck hat dieses Vorgehen? Warum erstellt man nicht einfach ein "normales" Objekt der Klasse die das Interface implementiert und verwendet dieses?

Herzlichen Dank
Ares

Uwe Raabe 20. Dez 2008 13:27

Re: Sinn und Zweck von Interfaces
 
Im Großen und Ganzen ist dein Verständnis von Interfaces durchaus richtig.

Zu der ersten Frage: GUIDS sind bei normaler Programmierung nicht zwingend notwendig. Es ist durchaus erlaubt, ein Interface ohne eine GUID zu deklarieren und zu benutzen und von IUnknown müssen sie auch nicht zwingend abgeleitet sein. Allerdings kann ich dann z.B. nicht mittels der Funktion "Supports" auf ein Interface abfragen - dazu braucht es zwingend eine GUID.

Zweite Frage: Die Verwendung einer Interface-Instanz anstatt einer Objekt-Instanz erlaubt es, für die Implementierung des Interfaces unterschiedliche Klassen zu verwenden, die dieses Interface (ggf. unterschiedlich) implementieren. Auch die Delegierung der Interface-Implementation an ein anderes Objekt (Stichwort: implements) ermöglicht so einige elegante Lösungen. Das die Beispiele häufig genauso durch abstrakte oder normale Klassen gelöst werden können liegt meistens an der Einfachheit der Beispiele.

Auch bei COM-Interfaces ist es nichts anderes: jedes COM-Interface wird auch durch eine oder mehrere Klassen implementiert. Diese können in C++ oder Delphi geschrieben sein, das ist für das Interface egal. Auch kann die eigentliche Implementierung jederzeit geändert werden ohne das Interface zu beeinflussen.

Apollonius 20. Dez 2008 15:21

Re: Sinn und Zweck von Interfaces
 
In Delphi sind müssen alle Interfaces von IInterface abgeleitet werden (dies ist ein Alias für IUnknown). Das ist oftmals sehr ärgerlich, Delphi lässt jedoch keine neuen Basis-Interfaces zu. Die Referenzzählung kannst du ausschalten, indem du in deinen Klassen _AddRef und _Release leer implementierst.
Die GUID dient dazu Interfaces eindeutig zu identifizieren. In Delphi benötigst du die GUID, um den as-Operator verwenden zu können, da dieser implizit QueryInterface verwendet, welches die GUID des Zielinterfacetyps erwartet.

Bezüglich der Interface-Objekte: Die selbe Frage kannst du für abstrakte Klassen stellen und beantworten: Abstrakte Klassen und Interfaces müssen immer konkretisiert werden. In deinem Beispiel Verwendung von Interfaces natürlich nicht sinnvoll. Interessant wird es, wenn eine Routine mit Objekten arbeitet, die sie nicht selbst erstellt hat. Ein Binärbaum könnte zum Beispiel Objekte verwalten, die ein Interface IComparable implementieren (das lässt sich mit Generics noch weiter verbessern, aber das ist hier nicht das Thema): Dadurch kann der Binärbaum Vergleiche durchführen, aber ohne sich auf eine konkrete Klasse festzulegen.

I.A 14. Apr 2009 15:32

Re: Sinn und Zweck von Interfaces
 
Hallo,

ich stöbere soeben mal wieder und bin auf dieses Beispiel gestossen.

Meine Frage hieraus:

Wenn mein Interface von einer anderen Klasse in einer DLL implementiert wird, muss ich da nicht im Interface den Konstruktor der implementierenden Klasse verfügbar machen, damit ich die Klasse, die ich über das Interface ansprechen will, auch zuverlässig erzeugen kann. Das gleiche müsste dann natürlich für den Destruktor gelten, der die Klasse am Ende wieder frei gibt. Und was ist mit der Free Methode. Die muss doch dann auch im Interface verfügbar sein oder?

quendolineDD 14. Apr 2009 15:39

Re: Sinn und Zweck von Interfaces
 
Nein. Du hast das glaube ich falsch verstanden.
Die Klasse in der DLL implementiert dein Interface. Du hast da gar nichts zu tun :)
Dein Interface legt die Methoden fest, welche implementiert sein müssen und über diese kannst du mit der Klasse kommunizieren. Wie diese in der Klasse implementiert sind, brauchst du nicht zu wissen.

Und TInterfacedObject implementiert automatisch _AddRef und _Release.

xaromz 14. Apr 2009 15:45

Re: Sinn und Zweck von Interfaces
 
Hallo,
Zitat:

Zitat von I.A
Wenn mein Interface von einer anderen Klasse in einer DLL implementiert wird, muss ich da nicht im Interface den Konstruktor der implementierenden Klasse verfügbar machen, damit ich die Klasse, die ich über das Interface ansprechen will, auch zuverlässig erzeugen kann.

Ein Interface kann keinen Konstruktor beinhalten, da ein Interface ja nur die Fassade für ein vorhandenes Objekt ist. Es gibt z. B. keine statischen Interface-Methoden. Folglich benötigst Du eine Factory, welche Dir ein Interface zurückgibt. Microsoft mach das z. B. so mit den CoCreate* Funktionen.
Zitat:

Zitat von I.A
Das gleiche müsste dann natürlich für den Destruktor gelten, der die Klasse am Ende wieder frei gibt.

Mit Interfaces gibt es eigentlich keinen Destruktor, da Interfaces normalerweise über die Referenzzählung verwaltet werden.
Zitat:

Zitat von I.A
Und was ist mit der Free Methode. Die muss doch dann auch im Interface verfügbar sein oder?

Hier gilt natürlich das gleiche wie beim Destruktor, ohne Destruktor ist auch Free sinnlos. Wenn Du natürlich ohne Referenzzählung arbeitest (bzw. diese ausschaltest), dann kannst Du auch Free ins Interface aufnehmen. Damit bewegst Du Dich aber außerhalb der COM-Regeln und verlierst einige Vorzüge (bzw. Nachteile :wink: ) von Interfaces, z. B. die automatische Objektfreigabe. Solange Du Dir dessen bewusst bist und die Schnittstelle nicht veröffentlichen willst, ist das aber kein Problem.

Gruß
xaromz

mjustin 14. Apr 2009 16:55

Re: Sinn und Zweck von Interfaces
 
Zitat:

Zitat von Ares
Warum erstellt man nicht einfach ein "normales" Objekt der Klasse die das Interface implementiert und verwendet dieses?

Um Abhängigkeiten zu eliminieren. Ein Interface ist zum Beispiel da sehr vorteilhaft, wo es eine Spezifkation gibt, zu der verschiedene Hersteller verschiedene Implementierungen entwickeln können.

Natürlich könnten diese auch alle von einem vorgegebenen Basisobjekt ableiten, und die abstrakten Methoden überschreiben. Bei Interfaces ist man jedoch freier, da die Basisklasse dann von jedem Implementierer frei gewählt werden kann.

Beispiel: IXMLDocument, dazu gibt es drei (oder mehr) verschiedene Implementierungen.

Cheers,


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