Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Cast von TObject nach Interface?
Luuuz - So 09.05.10 15:08
Titel: Cast von TObject nach Interface?
Hallo,
ich implementiere gerade eine Observer Pattern. Hierzu muss ich mir sämtliche Observer in einer dynamischen Liste von TObjects merken.
Später will ich auf diesen Objekten die Methode "Notify" aufrufen. Sprich ich muss diese Objekte nach IObserver casten. (IObserver enthält die Vereinbarung über die Notify Methode).
Normalerweise müsste ich folgendes schreiben:
Delphi-Quelltext
1:
| IObserver(MyList.Items[i]).Notify(); |
oder
Delphi-Quelltext
1:
| (MyList.Items[i] as IObject).Notify(); |
Diese Ansätze funktionieren leider nicht. Die Variante mit "as" könnte ich nur einsetzen, wenn TObject immer das Interface IObserver implementieren würde.
Gibt es hierfür einen Trick, oder ist dieser Anwendungsfall wirklich nicht vorgesehen ?!?!
Besten Dank im Voraus!
Tobias
Moderiert von
Narses: Topic aus Sonstiges (Delphi) verschoben am Mo 10.05.2010 um 00:28
Moderiert von
Narses: B- durch Delphi-Tags ersetzt
jaenicke - So 09.05.10 16:54
Sollte das nicht mit TInterfaceList besser gehen?
Und davon unabhängig: Wenn du auf die Klasse castest, die das Interface implementiert, kannst du dann nicht auch auf dein Interface casten?
Und warum eigentlich TObject? Ist da nicht TInterfacedObject passender?
Luuuz - So 09.05.10 17:22
Hallo jaenicke,
vielen Dank für die Antwort.
Ich verwende die TObjectList, deshalb habe ich aus Ausgangsdatentyp TObject.
Alle Elemente dieser Liste implementieren das Interface IObserver und sind bereits initialisierte GUI Controls.
In der TInterfaceList kann ich meines Wissens nach nur Interfaces speichern. Ich benötige aber eine Liste in der dich die "fertigen" Objekte speichern kann.
Wenn ich anstatt der TObjectList ein statisches IObserver Array verwende funktioniert es einwandfrei.
Eine dynamische Liste würde sich für den Anwendungsfall aber eher anbieten...
Gruß
Tobias
jaenicke - So 09.05.10 18:27
Wie ich schon sagte: Mit Cast auf einen gemeinsamen Vorfahren, der das Interface implementiert, geht es doch.
// EDIT:
Um es deutlich zu machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| ITest = interface procedure Test; end;
TTest = class(TInterfacedObject, ITest) public procedure Test; end;
var a: TObjectList; begin ITest(TTest(a.Items[0])).Test; |
Geht ;-)
baka0815 - Fr 25.06.10 16:05
jaenicke: Das macht aber überhaupt keinen Sinn.
Wenn ich erst auf einen gemeinsamen Vorfahren casten muss, der kein Interface ist, kann ich statt dem Interface auch eine abstrakte Klasse verwenden - durch das Interface hätte ich nichts gewonnen.
Tatsächlich muss man aber scheinbar, wie du gesagt hast, eine
TInterfaceList verwenden. Das funktioniert dann problemlos - auch mit den "fertigen" Objekten:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| type IMeinInterface = interface procedure Test; end;
type TMeineKlasse = class(TInterfacedObject, IMeinInterface) procedure Test; end;
procedure Test(Intf: IMeinInterface); var Liste: TInterfaceList; I: Integer; begin Liste := TInterfaceList.Create; try Liste.Add(Intf); Intf.Test; for I := 0 to Liste.Count - 1 do IMeinInterface(Liste.Items[I]).Test; Liste.Remove(Intf); finally Liste.Free; end; end;
procedure Test2; begin Test(TMeineKlasse.Create); end; |
delfiphan - Fr 25.06.10 17:27
Du kannst ein "nacktes" Objekt nicht direkt in ein Interface casten, es sei denn du verwendest GUIDs oder machst den Umweg über die konkrete Klasse.
Der Grund dafür ist, dass der Interface-Pointer <> Objekt-Pointer ist und der Offset auf die Adresse auf die Functiontable unbekannt ist. Wenn du GUIDs verwendest, kannst du über QueryInterface bzw. über Supports() auf Interfaces casten bzw. herausfinden, ob ein Interface implementiert wird.
Am Rande bemerkt: Das Observer-Pattern wird eher im Bereich Java verwendet. In Delphi gibt's Events, wobei man die zwei Dinge nicht gleichsetzen kann.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!