Implementiert eine Komponente ein Interface?
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Implementiert eine Komponente ein Interface?
Ich habe einige eigene Komponenten entwickelt (von Standard LCL Komponenten abgeleitet), die alle das Interface IfdData implementieren sollen. Eine der Interface Methoden heisst z.B. Clear.
Jetzt würde ich gerne zur Laufzeit alle Komponenten einer Form durchgehen und bei den Komponenten, die mein Interface unterstützen, die Methode Clear aufrufen. Komponenten, die das Interface nicht unterstützen, sollen dabei einfach übergangen werden (die haben ja keine Clear Methode). Ich habe jetzt eine Weile herumprobiert, aber ich komme nicht drauf, wie man das syntaktisch richtig umsetzt.
Jetzt würde ich gerne zur Laufzeit alle Komponenten einer Form durchgehen und bei den Komponenten, die mein Interface unterstützen, die Methode Clear aufrufen. Komponenten, die das Interface nicht unterstützen, sollen dabei einfach übergangen werden (die haben ja keine Clear Methode). Ich habe jetzt eine Weile herumprobiert, aber ich komme nicht drauf, wie man das syntaktisch richtig umsetzt.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Implementiert eine Komponente ein Interface?
TObject.GetInterface() dient zu diesem Zweck:
https://www.freepascal.org/docs-html/cu ... rface.html
Das Interface muss eine GUID (bei COM-Interface) oder einen ID-string (bei Corba-Interface) haben.
https://www.freepascal.org/docs-html/cu ... rface.html
Das Interface muss eine GUID (bei COM-Interface) oder einen ID-string (bei Corba-Interface) haben.
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Re: Implementiert eine Komponente ein Interface?
Das schaut so aus, als wäre es, was ich brauche - aber wie ich es verwenden muss, ist mir auch nach dem Lesen der Dokumentation noch immer nicht klar.
1. Wie komme ich zum Parameter GUID?
Ich deklariere das Interface beispielsweise als
IfdData = Interface ['{0AB00115-0734-0184-C000-0C5600052148}'']
(Nebenbei: Gibt es eigentlich irgend welche Richtlinien, wie man den GUID String aufbauen soll, oder macht man das völlig willkürlich? In der Delphi-IDE gibt es glaube ich sogar ein Tastaturkürzel, das einen GUID String generiert)
Woher bekomme ich die GUID Variable - oder muss ich den GUID-String zu Fuß in den GUID Typ konvertieren?
Und was übergebe ich im Parameter obj? Die Komponente selbst steht doch schon vor dem Punkt: abc.GetInterface( guid, ????); Was muss denn da hin? obj ist ein OUT Parameter.
1. Wie komme ich zum Parameter GUID?
Ich deklariere das Interface beispielsweise als
IfdData = Interface ['{0AB00115-0734-0184-C000-0C5600052148}'']
(Nebenbei: Gibt es eigentlich irgend welche Richtlinien, wie man den GUID String aufbauen soll, oder macht man das völlig willkürlich? In der Delphi-IDE gibt es glaube ich sogar ein Tastaturkürzel, das einen GUID String generiert)
Woher bekomme ich die GUID Variable - oder muss ich den GUID-String zu Fuß in den GUID Typ konvertieren?
Und was übergebe ich im Parameter obj? Die Komponente selbst steht doch schon vor dem Punkt: abc.GetInterface( guid, ????); Was muss denn da hin? obj ist ein OUT Parameter.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Implementiert eine Komponente ein Interface?
Dann kannst dubraunbär hat geschrieben:Das schaut so aus, als wäre es, was ich brauche - aber wie ich es verwenden muss, ist mir auch nach dem Lesen der Dokumentation noch immer nicht klar.
1. Wie komme ich zum Parameter GUID?
Ich deklariere das Interface beispielsweise als
IfdData = Interface ['{0AB00115-0734-0184-C000-0C5600052148}'']
Code: Alles auswählen
if <objektinstanz>.getinterface('{0AB00115-0734-0184-C000-0C5600052148}',<interfacevariable>) then begin
tue etwas mit dem interface
end;
Diese ID soll "Globally Unique" also welt- oder universumweit einmalig sein.(Nebenbei: Gibt es eigentlich irgend welche Richtlinien, wie man den GUID String aufbauen soll, oder macht man das völlig willkürlich?
Das gibt es in Lazarus sicher auch. In MSEide wäre es RightClick-'Insert GUID'.In der Delphi-IDE gibt es glaube ich sogar ein Tastaturkürzel, das einen GUID String generiert)
Siehe oben. Eine andere Option istWoher bekomme ich die GUID Variable - oder muss ich den GUID-String zu Fuß in den GUID Typ konvertieren?
Code: Alles auswählen
if <objektinstanz>.getinterface(stringtoguid('{0AB00115-0734-0184-C000-0C5600052148}'),<interfacevariable>) then begin
tue etwas mit dem interface
end;
Code: Alles auswählen
if <objektinstanz>.getinterface(<interfacetyp>,<interfacevariable>) then begin
tue etwas mit dem interface
end;
"obj" ist die Interface Variable.Und was übergebe ich im Parameter obj? Die Komponente selbst steht doch schon vor dem Punkt: abc.GetInterface( guid, ????); Was muss denn da hin? obj ist ein OUT Parameter.
PS: Falls du COM-Interface verwendest (die Standardeinstellung), solltest du dir überlegen, ob nicht CORBA-Interface besser geeignet wären.
Zuletzt geändert von mse am Mi 3. Okt 2018, 08:35, insgesamt 2-mal geändert.
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Re: Implementiert eine Komponente ein Interface?
Danke für die Antwort, mit den Infos sollte ich weiterkommen.
Ich benötige die Interfaces in dem Framework hier eigentlich nur, um auf einer abstrakten Ebene manche Aufgaben für die Komponenten einer Form automatisch erledigen zu können, die die entsprechende Funkionalität bereitstellen. Wenn es auf der Form noch andere Komponenten gibt, dann muss sich der Programmierer der Form (zur Zeit meistens auch ich selbst) in einer Callback Routine um diese Komponenten individuell kümmern.
Keine Ahnung, ob Corba da irgend einen Vorteil bieten würde. Es geht hier explizit nicht um Schnittstellen nach außen zu anderen Programmen.
Was ich gerne wissen würde, ist noch, ob die Prüfung auf Vorhandensein des Interfaces zeitaufwändig ist - ich vermute aber eher (und hoffe), dass das nicht der Fall ist.
Edit: Nochmals danke, das hat jetzt auf Anhieb funktioniert.
Ich benötige die Interfaces in dem Framework hier eigentlich nur, um auf einer abstrakten Ebene manche Aufgaben für die Komponenten einer Form automatisch erledigen zu können, die die entsprechende Funkionalität bereitstellen. Wenn es auf der Form noch andere Komponenten gibt, dann muss sich der Programmierer der Form (zur Zeit meistens auch ich selbst) in einer Callback Routine um diese Komponenten individuell kümmern.
Keine Ahnung, ob Corba da irgend einen Vorteil bieten würde. Es geht hier explizit nicht um Schnittstellen nach außen zu anderen Programmen.
Was ich gerne wissen würde, ist noch, ob die Prüfung auf Vorhandensein des Interfaces zeitaufwändig ist - ich vermute aber eher (und hoffe), dass das nicht der Fall ist.
Edit: Nochmals danke, das hat jetzt auf Anhieb funktioniert.
Zuletzt geändert von braunbär am Di 2. Okt 2018, 21:29, insgesamt 1-mal geändert.
-
- Beiträge: 582
- Registriert: Sa 22. Okt 2016, 23:12
- OS, Lazarus, FPC: W10, L 3.8
- CPU-Target: 32+64bit
- Wohnort: Dresden
Re: Implementiert eine Komponente ein Interface?
GUID Tastenkürzel: Shift+Strg+G siehe Menü -> Quelltext -> Einfügen allgemein -> GUID einfügen
selbst eine erzeugen:
selbst eine erzeugen:
Code: Alles auswählen
var
T : TGUID;
begin
CreateGUID(T);
ShowMessage(GUIDToString(T));
end;
LG Maik
Windows 10,
- Lazarus 3.8 (stable) + fpc 3.2.2 (stable)
- Lazarus 4.99 (trunk) + fpc 3.3.1 (main/trunk)
Windows 10,
- Lazarus 3.8 (stable) + fpc 3.2.2 (stable)
- Lazarus 4.99 (trunk) + fpc 3.3.1 (main/trunk)
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Re: Implementiert eine Komponente ein Interface?
Gut zu wissen.
Habs gerade ausprobiert. So schön wie meine GUID sind die aber nicht
Habs gerade ausprobiert. So schön wie meine GUID sind die aber nicht

-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Implementiert eine Komponente ein Interface?
Dann würde ich auf jeden Fall CORBA einsetzen.braunbär hat geschrieben:Danke für die Antwort, mit den Infos sollte ich weiterkommen.
Ich benötige die Interfaces in dem Framework hier eigentlich nur, um auf einer abstrakten Ebene manche Aufgaben für die Komponenten einer Form automatisch erledigen zu können, die die entsprechende Funkionalität bereitstellen. Wenn es auf der Form noch andere Komponenten gibt, dann muss sich der Programmierer der Form (zur Zeit meistens auch ich selbst) in einer Callback Routine um diese Komponenten individuell kümmern.
Die üblichen COM -Interface sind referenzgezählt und vertragen sich schlecht mit aus dem Programm aufgerufenem destroy(), speziell die Kombination TComponent/COM-Interface ist ein Albtraum. CORBA-Interface haben diesen Nachteil nicht, da hat man alles unter Kontrolle; durch die fehlende Referenzzählung sind sie erst noch schneller.Keine Ahnung, ob Corba da irgend einen Vorteil bieten würde. Es geht hier explizit nicht um Schnittstellen nach außen zu anderen Programmen.
Die Suche in den Tabellen ist aufwendig. CORBA hat den Vorteil, dass als ID ein beliebiger auch kurzer String verwendet werden kann, der lediglich in der Applikation einmalig sein muss. MSEide erzeugt solche ID's mit RightClick-'Insert UID'.Was ich gerne wissen würde, ist noch, ob die Prüfung auf Vorhandensein des Interfaces zeitaufwändig ist - ich vermute aber eher (und hoffe), dass das nicht der Fall ist.
Schneller als die Tabellensuche zur Laufzeit ist Typenkonvertierung zur Kompilierzeit wenn der Klassentyp bekannt ist.
Code: Alles auswählen
type
{$interfaces corba}
itest = interface ['AA']{0} //ID not used in example.
procedure test();
end;
ttest = class(itest)
protected
procedure test();
end;
[...]
var
t1: ttest;
[...]
itest(t1).test();
Code: Alles auswählen
const
id_test = 'AA.braunbaer';{0}
type
{$interfaces corba}
itest = interface [id_test]
procedure test();
end;
Die Tabellenabfrage ist auch in der Form
Code: Alles auswählen
var
t1: ttest;
intf1: itest;
[...]
if t1.getinterface(itest,intf1) then begin
intf1.test();
end;
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Re: Implementiert eine Komponente ein Interface?
Momentan funktioniert es mit den standard COM Interfaces. Ich werde aber Corba auch noch ausprobieren. Wenn ich es richtig verstehe, muss ich nur in allen Units, die so ein Interface verwenden, {$interfaces corba} vor die erste Verwendung/Deklaration einfügen, und dann kann ich, wenn ich will, statt der GUID auch einen kürzeren Namen verwenden.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Implementiert eine Komponente ein Interface?
Ja, und es gibt keine Probleme mit Referenzzählung.
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Implementiert eine Komponente ein Interface?
So ne ganz dumme frage, warum verwendet man nicht einfach den is operator?
Das macht intern zwar auch den kram mit den GUIDs aber als entwickler muss man sich nicht um die guids kümmern. Ledeglich wenn man ein Interface schreibt einmal in Lazarus STRG+SHIFT+G drücken um die GUID zu generieren, danach kann man die GUID direkt wieder vergessen.
Der as Operator würde im notfall auch eine Exception werfen wenn die Klasse das Interface nicht implementiert. Daher kann man auch einfach mit einem try except arbeiten
Code: Alles auswählen
if MyObj is ISomeInterface then
(MyObj as ISomeInterface).SomeInterfaceMethod;
Der as Operator würde im notfall auch eine Exception werfen wenn die Klasse das Interface nicht implementiert. Daher kann man auch einfach mit einem try except arbeiten
Code: Alles auswählen
try
ifVar := SomeObj as ISomeInterface
except
on E: Exception do
// kein ISomeInterface typ
end;
-
- Beiträge: 463
- Registriert: Do 8. Jun 2017, 18:21
- OS, Lazarus, FPC: Windows 10 64bit, Lazarus 3.6, FPC 3.2.2
- CPU-Target: 64Bit
- Wohnort: Wien
Re: Implementiert eine Komponente ein Interface?
Versteh ich auch nicht. Es wäre die intuitiv naheliegendste Variante, und es war eigentlich das erste Konstrukt, das ich versucht habe - erst nachdem der Compiler das nicht wollte, habe ich angefangen, die Doku durchzustöbern, und dann den Thread hier eröffnet.
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Implementiert eine Komponente ein Interface?
Du musst eine guid erstellen (Strg+Shift+g in laz) damit müsste es funktionierenbraunbär hat geschrieben:Versteh ich auch nicht. Es wäre die intuitiv naheliegendste Variante, und es war eigentlich das erste Konstrukt, das ich versucht habe - erst nachdem der Compiler das nicht wollte, habe ich angefangen, die Doku durchzustöbern, und dann den Thread hier eröffnet.
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Implementiert eine Komponente ein Interface?
Performance?Warf hat geschrieben:So ne ganz dumme frage, warum verwendet man nicht einfach den is operator?
Das ist hier auch nicht anders:Das macht intern zwar auch den kram mit den GUIDs aber als entwickler muss man sich nicht um die guids kümmern. Ledeglich wenn man ein Interface schreibt einmal in Lazarus STRG+SHIFT+G drücken um die GUID zu generieren, danach kann man die GUID direkt wieder vergessen.Code: Alles auswählen
if MyObj is ISomeInterface then (MyObj as ISomeInterface).SomeInterfaceMethod;
Code: Alles auswählen
if t1.getinterface(itest,intf1) then begin
intf1.test();
end;
Hier ist die Performance noch schlechter. Verfolge mal mit dem Debugger was so alles passiert. Vor allem das Auslösen einer exception ist sehr aufwendig aber auch das einfache try/except ist nicht kostenlos. In MSElang verwende ich "Zero-cost exception handling" aber auch dort ist nur der exceptionlose Durchlauf durch die Exception-Strukturen ohne Zusatzaufwand und die EXE wird durch die abgelegten Verwaltungsinformationen grösser.Der as Operator würde im notfall auch eine Exception werfen wenn die Klasse das Interface nicht implementiert. Daher kann man auch einfach mit einem try except arbeitenCode: Alles auswählen
try ifVar := SomeObj as ISomeInterface except on E: Exception do // kein ISomeInterface typ end;
-
- Lazarusforum e. V.
- Beiträge: 395
- Registriert: Sa 15. Mai 2010, 13:46
- CPU-Target: 64 bit
- Kontaktdaten:
Re: Implementiert eine Komponente ein Interface?
Hallo, hier ein Beispiel, was passiert, wenn man keine IDs für die Interfaces festgelegt hat:So ne ganz dumme frage, warum verwendet man nicht einfach den is operator?
Code: Alles auswählen
program interfaceproblem;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, sysutils;
type
{$interfaces corba}
IInt1 = interface
procedure test1;
end;
IInt2 = interface
procedure test2;
end;
TObj1 = class(IInt1)
procedure test1;
end;
TObj2 = class(TObj1, IInt2)
procedure test2;
end;
procedure TObj1.test1;
begin
writeln('test 1 called');
end;
procedure TObj2.test2;
begin
writeln('test 2 called');
end;
procedure test;
var
int : IInt1;
begin
writeln('start test');
int := TObj2.create as IInt1;
int.test1; // ERROR: prints test 2 called
end;
begin
test;
end.

Hier im Beispiel überschreibt die Implementierung von IInt2 offenbar irgendwie die Memory Tabelle von IInt1. Das geht auch, wenn die Methoden vollkommen verschiedene Parameter verwenden und dann sucht man den Fehler

Wieso kompiliert der Code im Beispiel überhaupt ohne Fehlermeldung?