Hallo zusammen,
bisher habe ich mich noch nicht mit der Implementierung von Interfaces befasst. Soll heißen, das ist für mich Neuland, zumindest in Free Pascal. Deshalb wollte ich das Programm aus dem Wiki (https://wiki.freepascal.org/How_To_Use_Interfaces) kompilieren und damit etwas spielen. Beim Kompilieren bekomme ich aber in Zeile 69 an der Stelle "THook(FHook).Free;" eine Warnung, die ich nicht verstehe: "interfacesygenerics.lpr(69,5) Warning: Class types "ITestInterface" and "THook" are not related".
Würde mir bitte jemand von Euch verraten, was sie bedeutet? Inwiefern sind die beiden Klassen "not related"? THook ist doch die Implementierung von ITestInterface. Oder habe ich da etwas falsch verstanden?
Vielen Dank für Eure Hilfe!
Grüße,
Ralf
Class types not related?
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Class types not related?
Ich kenn mich da auch nicht so sehr aus, aber ist doch irgendwie sinnig. Sagen wir du hast 20 verschiedene Typen die vom selben Interface erben, THook(irgendwas) zu schreiben ist also in 19 von 20 fällen falsch. Darum macht ne warnung sinn. Au0erdem ist doch das genau der witz an interfaces, das du eben nicht wissen musst was für ein Typ unterliegt. Wenn du weißt das es ein THook ist, dann macht es überhaupt keinen sinn an dieser stelle ein Interface zu benutzen
Außerdem noch ein paar sachen.
1. Der destructor ist immer Virtual, d.h. du kannst einfach TObject(...).Free schreiben, das ist auf jeden fall korrekt (oder FreeAndNil benutzen)
2. Es gibt den As operator, der zur laufzeit (mittels RTTI) überprüft ob die Konvertierung auch Legal ist, d.h. ob der Pointer wirklich auf die entsprechende Instanz zeigt. Typ(...) ist rein zur kompilezeit und rein statisch, solang also performance nicht sonderlich relevant ist, gibt es keinen grund Typ(...) statt (... as Typ) zu schreiben, da das keinen fehler wirft, und im worst case ohne fehler einfach dein programm in einen undefinierten State bringt, sodass es komplett falsche sachen macht, du aber nicht rausfinden kannst wo der fehler liegt (ein fehler der dir um die Ohren fliegt ist eigentlich immer zu bevorzugen)
3. COM interfaces sind referenzgezählt, du kannst also auch ganz einfach den Ref counter implementieren, dann brauchst du gar kein Free mehr aufzurufen
Außerdem noch ein paar sachen.
1. Der destructor ist immer Virtual, d.h. du kannst einfach TObject(...).Free schreiben, das ist auf jeden fall korrekt (oder FreeAndNil benutzen)
2. Es gibt den As operator, der zur laufzeit (mittels RTTI) überprüft ob die Konvertierung auch Legal ist, d.h. ob der Pointer wirklich auf die entsprechende Instanz zeigt. Typ(...) ist rein zur kompilezeit und rein statisch, solang also performance nicht sonderlich relevant ist, gibt es keinen grund Typ(...) statt (... as Typ) zu schreiben, da das keinen fehler wirft, und im worst case ohne fehler einfach dein programm in einen undefinierten State bringt, sodass es komplett falsche sachen macht, du aber nicht rausfinden kannst wo der fehler liegt (ein fehler der dir um die Ohren fliegt ist eigentlich immer zu bevorzugen)
3. COM interfaces sind referenzgezählt, du kannst also auch ganz einfach den Ref counter implementieren, dann brauchst du gar kein Free mehr aufzurufen
Re: Class types not related?
Hallo Warf,
Danke für Deine Erklärungen. Ich denke, das hilft mir schon mal weiter. In dem von Dir geschilderten Fall macht die Warnung tatsächlich Sinn.
Was den Ref-Counter betrifft reicht es doch, wenn ich bei der Implementierung eines Interfaces auch von TInterfacedObject oder einem Nachkommen erbe. Dann wird die Instanz freigegeben, sobald sie nicht mehr benötigt wird, richtig?
Grüße,
Ralf
Danke für Deine Erklärungen. Ich denke, das hilft mir schon mal weiter. In dem von Dir geschilderten Fall macht die Warnung tatsächlich Sinn.
Was den Ref-Counter betrifft reicht es doch, wenn ich bei der Implementierung eines Interfaces auch von TInterfacedObject oder einem Nachkommen erbe. Dann wird die Instanz freigegeben, sobald sie nicht mehr benötigt wird, richtig?
Grüße,
Ralf
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Class types not related?
Code: Alles auswählen
Was den Ref-Counter betrifft reicht es doch, wenn ich bei der Implementierung eines Interfaces auch von TInterfacedObject oder einem Nachkommen erbe. Dann wird die Instanz freigegeben, sobald sie nicht mehr benötigt wird, richtig?
aber, das gilt nur für interface referenzen, d.h. sobald du die irgendwo als nicht interface abspeicherst (z.B. in ner variable mit dem echten Klassentyp), wird dafür keine referenz gezählt
Wenn du das nicht willst kannst du einfach CORBA interfaces benutzen (am anfang der Unit {$Interfaces CORBA} schreiben, oder die Refenzzählermethoden mit noops überladen (also einfach nix machen)
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Class types not related?
Also die Meldung bekommst du normalerweise wenn du einen TypeCast machen willst mit 2 Klassen die nicht aus der gleichen Vererbungslinie stammen und somit auch nicht per TypeCast zugewiesen werden können.
Beispiel:
Die Klassen TClass1 und TClass3 sind nicht von der gleichen Basisklasse abgeleitet und somit ist der Typecast falsch.
TClass1 und TClass2 sind in der gleichen Vererbungslinie. Somit kann eine Instanz von TClass2 auch an eine Variable vom Typ TClass1 zugewiesen werden.
Beispiel:
Code: Alles auswählen
type
TClass1 = class
end;
TClass2 = class ( TClass1 ) // TClass2 erbt von TClass1
end;
TClass3 = class // Hier beginnt eine neue Klassenhirarchie
end;
TClass4 = class ( TClass3 )
end;
procedure test;
var c1 : TClass1;
c3 : TClass3;
begin
c1 := TClass1.Create;
c3 := TClass3(c1);
end;
TClass1 und TClass2 sind in der gleichen Vererbungslinie. Somit kann eine Instanz von TClass2 auch an eine Variable vom Typ TClass1 zugewiesen werden.