Arbeiten mit Interfaces, wie macht man es korrect ? [Gelöst]

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Warf
Beiträge: 2129
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Arbeiten mit Interfaces, wie macht man es korrect ?

Beitrag von Warf »

corpsman hat geschrieben: Do 15. Mai 2025, 14:48 Weis jemand warum der Typecast nicht geht ? Bisher dachte ich immer dass der Unterschied zwischen dem Typecast und des "as" Operators nur der ist, das beim "as" der Compiler im hintergrund eine "versteckte" Prüfung einbaut und ggf. ne Exception wirft sollte es nicht compatibel sein...
Ein Typcast ist ein "betrachte dieses Objekt als XYZ", dabei wird aber das selbe objekt (also der selbe Pointer) verwendet. Bei Vererbung klappt das auch wunderbar weil da es keine Mehrfachvererbung gibt, und die Elterndaten einfach das Prefix des Objektes sind, der Pointer identisch ist.

Also wenn eine TStringList auf Addresse 1234 liegt, dann ist die instanz parent klasse TStrings die ersten paar bytes also z.B. 1234-1294 und die TStringList elemente folgen dann danach.

Bei Interfaces ist das nicht so, weil Interfaces in verschiedenen objekten vorkommen können, kann man da nicht einfach eine fixe umrechnung machen. Stattdessen muss zur Laufzeit in einer Tabelle nachgeschaut werden wo die Interface Daten liegen. Das macht der "as" operator.

Deshalb funktioniert kein Typecast

Beispiel:

Code: Alles auswählen

type
  IMyInterface = Interface
     ['{B08E4496-0A99-40F6-9F11-02811A0393BF}']
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)

  end;

var
  c: TMyClass;
begin
  c:=TMyClass.Create;
  WriteLn('Raw Pointer: ', IntPtr(c));
  WriteLn('Parent Pointer: ', IntPtr(TInterfacedObject(c)));
  WriteLn('Interface Pointer: ', IntPtr(c as IMyInterface));
end.
Ergebnis:

Code: Alles auswählen

Raw Pointer: 21702360
Parent Pointer: 21702360
Interface Pointer: 21702376
Sowohl C als TMyClass als auch als TInterfacedObject (Parent Klasse von TMyClass) haben den selben Ursprung im Speicher. Das Interface Objekt von IMyInterface ist allerdings woanders in dem Objekt verwart, in dem fall 16 bytes weiter hinten im Speicher (SizeOf(VMT) + SizeOf(TInterfacedObject.FRefCount) + SizeOf(TInterfacedObject.FDestroyCount)).

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1629
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Arbeiten mit Interfaces, wie macht man es korrect ? [Gelöst]

Beitrag von corpsman »

Danke für die Erklärung, wieder was gelernt ;)
--
Just try it

Antworten