Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Inkompatible Typen: 'IMyInterface' und 'TPersistent' (https://www.delphipraxis.net/102202-inkompatible-typen-imyinterface-und-tpersistent.html)

berens 24. Okt 2007 23:27


Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Hi!

Ich hab eine TComponentList voll mit unterschiedlichen Objekten, die alle garantiert ein IMyInterface haben.

Nun will ich über die ComponentList für ein einzelnes Objekt einen Wert über das Interface ändern. Wie geht das?

IMyInterface(SelectedObjects.Items[i]).x := 1;
--> Inkompatible Typen: 'IMyInterface' und 'TPersistent'

bla: IMyInterface;
bla := SelectedObjects.Items[i];
bla.x := 1;
--> Inkompatible Typen: 'IMyInterface' und 'TPersistent'

3_of_8 24. Okt 2007 23:37

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Ich bin mir nicht ganz sicher, aber es wäre durchaus möglich, dass das nicht geht - du musst eventuell wirklich auf eine Klasse casten, die das Interface implementiert - das kann theoretisch auch eine einfache Basisklasse sein, die nur das Interface implementiert - eventuell sogar alle Methoden als abstrakt. Von der leitest du dann alles andere, was das Interface implementiert, ab.

Aber ich arbeite nicht sehr viel mit Interfaces, könnte also sein, dass das auch anders möglich ist.

berens 24. Okt 2007 23:39

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Wenn das stimmt, dann wären Interfaces meiner Meinung nach kompletter Unsinn:

Ich habe einen TButton und ein TEdit, die beide die Prozedur .FooBar bekommen sollen. Wie soll ich denn aus den Beiden eine gemeinsame Basisklasse machen?

Weil Mehrfachvererbung in Delphi nicht geht, gibt es ja Interfaces. Ich fange aber leider eben erst mit an und kapier das noch nicht so ganz :/


Edit: OMG, alle Delphi-Interface-Tutorials die ich bisher gefunden habe, gehen davon aus, dass mir schon zur Entwicklungszeit bekannt ist, mit was für einem Objekt ich gerade arbeite. Klar, dann funktioniert das, mit Typecast auf TMyObject(foo).bla. Tjo, aber wenn das Objekt aus der ComponentList nun von der Klasse TFoo oder TBar ist, die auch das Interface haben bringt mir das afaik nix, weil der ja durch den Typecast auf die falsche Klasse den falschen Speicherbereich ausliest...

Flocke 24. Okt 2007 23:53

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Eigentlich (sofern es sich wirklich um eine TComponentList handelt) sollten die Elemente der Liste vom Typ TComponent sein, der wiederum IInterface implementiert und somit auf andere Interfaces castbar (Vorsicht: denglisch) ist. Die Fehlermeldung bzgl. TPersistent irritiert mich da ein wenig.

Zu deinem Nachtrag: du musst nicht wirklich den Typ des Objekts wissen, du musst nur eine gemeinsame Basisklasse wissen, die IInterface implementiert.

jbg 25. Okt 2007 00:00

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Zitat:

Zitat von berens
IMyInterface(SelectedObjects.Items[i]).x := 1;
--> Inkompatible Typen: 'IMyInterface' und 'TPersistent'

Gut dass das der Compiler abfängt. Hierbei würdest du den TPersistent-Zeiger als Interface-Zeiger interpretieren.

Zitat:

bla: IMyInterface;
bla := SelectedObjects.Items[i];
Hier verhindert der Compiler die Zuweisung, weil er keine Informationen über den Zusammenhang zwischen dem TPersistent und IMyInterface hat. Diesen Zusammenhang kann man leider nur bei der Deklaration mitteilen.


Bei TComponent kannst du den "as" Operator nutzen:
Delphi-Quellcode:
(SelectedObjects.Items[i] as IMyInterface).x := 1;


Wenn du jedoch mit TPersistent arbeitest, dass kein IInterface implementiert, also auch keine QueryInterface Methode besitzt, musst du auf die Supports() Funktionen ausweichen.
Delphi-Quellcode:
var
  bla: IMyInterface;
begin
  if Supports(SelectedObjects.Items[i], IMyInterface, bla) then
    bla.x := 1;
end;
Das ist ziemlich Umständlich, da hier der "as"-Operator nicht funktioniert weil TPersistent kein IInterface implementiert. Mit TInterfacedPersistent würde das kein Problem sein.

Kleine Hilfsfunktion wenn du einen Einzeiler haben willst.
Delphi-Quellcode:
function IntfCast(Instance: TObject; const IID: TGUID): IInterface;
begin
  if not Supports(Instance, IID, Result) then
    raise EIntfCastError.CreateRes(@SIntfCastError);
end;

var
  Persistent: TPersistent;
begin
  Persistent := Irgendwas;
  IMyInterface(IntfCast(Persistent, IMyInterface).x := 1;
end;

berens 25. Okt 2007 00:09

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Ok, zur Verteidigung von Delphi und Schlamperei meinerseits muss natürlich noch gesagt werden, dass dies (hab den Code ein paar Wochen nicht gesehen) keine einfache TComponentList ist, sondern vom Typ TLMDDesignObjects, was zwar auch eine Liste für Komponenten, aber keine TComponenList in diesem Sinne ist.

var
comp: TComponent;
begin
comp := TComponent(SelectedObjects[i]);
(comp as IMyInterface).DS := 1;

^-- scheint zu gehen

(TComponent(SelectedObjects[i]) as IMyInterface).DS := 1;

^-- scheint auch zu gehen



So, schon mal sehr gut dass wir soweit sind, Danke erstmal.

Diese Zeile kann man aber auf die Schnelle nicht mehr vereinfachen, denke ich mal?

Der "as" Operator prüft doch zur Laufzeit alle Objekte, ob die auch wirklich das Interface haben, sonst gibt's Exception. Korrekt, oder?

Danke nochmal für die Tips!

jbg 25. Okt 2007 00:14

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Zitat:

Zitat von berens
sonst gibt's Exception. Korrekt, oder?

Genau. Der haut dir das um die Ohren wenn es nicht passt.

berens 25. Okt 2007 00:15

Re: Inkompatible Typen: 'IMyInterface' und 'TPersistent'
 
Ok, Danke an Alle. Thema erfolgreich abgehakt. Gute N8.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:40 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 by Thomas Breitkreuz