![]() |
AW: Schon wieder: Warum Interfaces
Eine goldene Regel dafür kenne ich auch nicht, aber je dynamischer (besonders im Hinblick auf die Klassentruktur) und/oder offener (im Hinblick auf externe Schnittstellen) ein Projekt wird, desto sinnvoller wird der Gebrauch von Interfaces IMO.
|
AW: Schon wieder: Warum Interfaces
Zitat:
Wenn man also eine Darstellung für IMyInt hat, kann diese auch für IMyIntA und IMyIntB genutzt werden. Wobei man Ableitungen von Interfaces eher vermeiden sollte. Hier werden ja eher Funktionalitäten beschrieben und dabei ist es i.d.R. sinnvoll, viele kleine eigenständige Funktionalitäten (Interfaces) zu definieren als von anderen abzuleiten. Wenn man IMyInt1 und IMyInt2 und möchte jetzt ein IMyInt3, das die beiden anderen implementiert, könnte man ja nur von einem ableiten und müsste den anderen Bereich wieder nachbilden. Besser wäre es somit, in IMyInt3 nur die Neuerungen zu definieren und einer späteren Klasse alle drei Interfaces zuzuweisen: TMyClass = class(TInterfacedObject, IMyInt1, IMyInt2, IMyInt3) Also, da Vererbungen von Interfaces die Ausnahme sein werden, wäre für jedes Interface eine eigene Visualisierung zu regeln. Das kann man aber in Form von Bedingungsprüfungen in einer Unit regeln: if (TypeName = 'IMyInt1') then ... if (TypeName = 'IMyInt2') then ... Zitat:
Wenn man schon bei der Planung eines Projektes zu dem Schluss kommt, dort irgendwann mal zu landen, dann sollte man gleich mit Interfaces starten. So spart man sich den Aufwand der späteren Umstellung, da das doch auf einiges Auswirkungen hat. Ich habe gerade ein nicht sehr umfangreiches Projekt der Einfachheit halber mit Klassen begonnen und habe mich jetzt doch entschieden, das nochmal umzustellen. Das ist zwar etwas mehr Schreibarbeit aber der Ablauf und die Beziehungen der einzelnen Projektteile ist dadurch deutlich übersichtlicher. |
AW: Schon wieder: Warum Interfaces
Jetzt mal für ganz Dumme, also für mich:
wann Klassen, wann Interfaces? Das mit den Autos und Reifen habe ich kein bisschen verstanden, da ich die Gedanken dahinter nicht verstehe. |
AW: Schon wieder: Warum Interfaces
Zitat:
Folgender Fall:
Delphi-Quellcode:
IMyIntf1 = interface(IInterface)
procedure SomeMethod1(); procedure SomeMethod2(); end; IMyIntf2 = interface(IMyIntf1) // Hier noch abgeleitet von IMyIntf1 procedure SomeMethod3(); end;
Delphi-Quellcode:
TMyClass = class(TInterfacedObject, IMyIntf1, IMyIntf2) // Hier könnte man IMyIntf1 ja denke ich auch weglassen
procedure SomeMethod1(); procedure SomeMethod2(); procedure SomeMethod3(); end;
Delphi-Quellcode:
In dem Konstrukt mit der Ableitung des Interfaces 2 von 1 ist das oben gezeigte Beispiel kein Problem. Wenn ich aber jetzt
TMyOtherClass = class(TObject)
type private MyIntfInstance: IMyIntf2; // Hier die 2 beachten procedure CallInterfaceMethod; end; implementation procedure TMyOtherClass.CallInterfaceMethod; begin MyIntfInstance.SomeMethod1(); // Hier die 1 beachten. end;
Delphi-Quellcode:
gesondert behandele und in TMyClass implementiere, dann erhalte ich ja eine Fehlermeldung, dass
IMyIntf2
Delphi-Quellcode:
in dem Kontext nicht verfügbar ist.
SomeMethod1()
Nur wie löse ich jetzt das Problem? Ich will ja jetzt nicht so viele Interfacevariablen in meiner Klasse anlegen, wie meine Interfaceklasse Interfaces importiert. Das halte ich für sehr umständlich. Ich kenne zwar vom Hören die Methode Supports(), weiß aber nicht, in wiefern das darauf anzuwenden ist. Hat da jemand einen Tipp? |
AW: Schon wieder: Warum Interfaces
Ganz wichtig, @Jim Carey: Klassen IMMER! Interfaces dann wenn es sinnvoll ist (darüber streiten sich dann die Experten ;)) Ein Interface ersetzt keine Klasse, Interfaces sind "nur" Vorschriften darüber wie wirkliche Implementierungen auszusehen haben.
Sherlock |
AW: Schon wieder: Warum Interfaces
Zitat:
Danke. |
AW: Schon wieder: Warum Interfaces
Ich mache das normalerweise so:
Delphi-Quellcode:
type
IIntf1 = interface ['{AA7958DE-7A80-4F11-A5D5-A70BB3D51320}'] procedure SomeMethod1; procedure SomeMethod2; end; IIntf2 = interface ['{A25606F4-B121-4FA5-BF07-B40C7784FFB7}'] procedure SomeMethod3; end; TTestClass = class(TInterfacedObject, IIntf1, IIntf2) public //IIntf1 procedure SomeMethod1; procedure SomeMethod2; //IIntf2 procedure SomeMethod3; end; { TTestClass } procedure TTestClass.SomeMethod1; begin ShowMessage('SomeMethod1'); end; procedure TTestClass.SomeMethod2; begin ShowMessage('SomeMethod2'); end; procedure TTestClass.SomeMethod3; begin ShowMessage('SomeMethod3'); end; procedure TFormTest.Button1Click(Sender: TObject); var Test: IIntf1; Intf2: IIntf2; begin Test := TTestClass.Create; Test.SomeMethod1; if Supports(Test, IIntf2, Intf2) then Intf2.SomeMethod3; end; |
AW: Schon wieder: Warum Interfaces
Genau so. :thumb:
Ich will nur noch ergänzen: Um Supports nutzen zu können muss das Interface eine Guid haben. Und Supports liefert im letzten Parameter automatisch den Cast des übergebenen Objektes/Interfaces auf das im zweiten Parameter übergebene Interface zurück. Oder Nil wenn Supports nicht true ist. Ich hatte mich damit (auch?) zunächst schwer getan, aber es ist eigentlich ganz simpel. |
AW: Schon wieder: Warum Interfaces
@DeddyH: Danke. Super Beispiel. :thumb: Wird aber dann doch immer etwas aufwendig wenn man immer wieder mit Supports() abfragen muss. :|
Zitat:
Zitat:
|
AW: Schon wieder: Warum Interfaces
Ob ich nun Supports() aufrufen muss oder Dinge der Art
Delphi-Quellcode:
, komfortabler wird es nicht.
if MyObject is TDingens then
TDingens(myObject).Machwas; [edit] Nachtrag: stahli hat Recht, man kann das übrigens auch anders formulieren.
Delphi-Quellcode:
[/edit]
Supports(Test, IIntf2, Intf2);
if Assigned(Intf2) then Intf2.SomeMethod3; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05: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-2025 by Thomas Breitkreuz