2016-09-01 1 views
2

Gibt es einen gemeinsamen Vorfahren für Delphi-Delegaten, die mit der of object-Klausel deklariert sind?Ein gemeinsamer Vorgänger für Objektdelegaten in Delphi

Ich brauche einen gemeinsamen Vorfahren für TNotifyEvent und meine benutzerdefinierten Delegaten zu finden:

TMyEvent = procedure(Sender: TObject; msg: stringh); of object; 

eine universelle Methode zum Brennen dieser Ereignisse zu machen.

Sollte ich Zeiger verwenden? oder TObject?

+0

Können Sie als Beispiel angeben, was Sie zu tun versuchen. Im Moment sieht es so aus, als ob Sie versuchen, sich in den Fuß zu schießen, indem Sie Methoden aufrufen, ohne alle erforderlichen Parameter anzugeben. – Johan

+1

Ich glaube, Sie sind in der falschen Annahme, dass "Prozedur (Absender: TObject) von Objekt" und "Prozedur (Absender: TObject; xyz: TSomehting) von Objekt" irgendwie kompatibel sind. Sie sind nicht! Wenn Sie beim Aufruf nicht die richtige Signatur haben, werden Sie die falschen Parameter übergeben, die mit einem Fehler enden. – Johan

+0

Ich würde gerne eine Lösung mit Generika vorschlagen. Aber ich habe nicht genug Informationen, um eine vollständige Antwort zu formulieren. Versuchen Sie eine TList zu erstellen, die Sie dann anrufen können; ist das, was du versuchst zu tun? Wenn ja, habe ich eine einfache Antwort für dieses Problem. – Johan

Antwort

6

Sie müssen mit den Implementierungsdetails für method pointers und schmutzig gehen. Diese werden als sogenannter Doppelzeiger Wert gespeichert. Ein Zeiger für das Objekt des Methodenaufrufs (die Instanz) und ein Zeiger für die Methode selbst (der Code).

Sie können den Typ TMethod aus der Einheit System verwenden, um Methodenzeiger darzustellen. Seine Erklärung sieht so aus (mit den Vergleichsoperator für Einfachheit entfernt):

type 
    TMethod = record 
    Code, Data: Pointer; 
    end; 

Sie benötigen eine Typumwandlung verwenden Zuordnungen zwischen diesen Typen zu machen:

uses 
    System.Classes; 

var 
    Event: TNotifyEvent; 
    Method: TMethod; 

begin 
    Method := TMethod(Event); 
    TMethod(Event) := Method; 
end. 

Offensichtlich nichts davon ist typsicher Sie müssen also auf Korrektheit achten. Der Compiler kann Ihnen nicht helfen. Es gibt nichts wie den Konvertierungsoperator "checked type", as, um mit Methodenzeigern zu arbeiten. Das heißt, dass Sie bei der Umwandlung von TMethod in einen bestimmten Methodenzeigertyp darauf achten müssen, dass die TMethod -Instanz wirklich eine Instanz des Methodenzeigers ist, in den Sie einwerfen. Stellen Sie sich diesen Vorgang so vor, als würde er von einem getippten Zeiger auf einen nicht typisierten Zeiger umwandeln und dann wieder zurück.

Nun, wenn Sie willkürlich Methodenzeiger in TMethod Instanzen speichern möchten, ist das in Ordnung. Was passiert aber, wenn Sie diese Methoden später auslösen müssen? Sie müssen wissen, welcher Typ von Methodenzeiger wirklich hinter jeder TMethod Instanz steht. Damit Sie wissen, wie Sie es umsetzen, welche Argumente es benötigt und wie Sie es nennen. Das bedeutet, dass Sie neben der eigentlichen Methode zusätzliche Informationen über den wahren Typ der Methode speichern müssen.

Also ich denke, dass ich vielleicht die Frage beantwortet habe, die du gestellt hast, aber ich bin mir nicht sicher, dass es dir von großem Nutzen sein wird. Um zu verstehen, dass wir wirklich mehr darüber wissen müssen, was Sie erreichen wollen und welche Informationen Sie wann haben. Wenn Sie beispielsweise die Argumente kennen, die an die Methode zu dem Zeitpunkt übergeben werden sollen, an dem Sie sie speichern müssen, können Sie die Variable erfassen und in eine anonyme Methode umbrechen. Das würde dir erlauben, die Typensicherheit beizubehalten und irgendwelche der eher zweifelhaften Modelle, die ich oben demonstriere, zu vermeiden. Vielleicht benötigen Sie partial application, um Ihre inhomogenen Methodenzeiger so anzupassen, dass sie dieselbe Schnittstelle haben. In diesem Fall können wieder anonyme Methoden helfen.

+0

Ja, das ist richtig. In Anbetracht der Typsicherheit denke ich, dass Sie die Antwort von hinten nach vorne haben. Sie sollten zuerst mit der typsicheren Option beginnen und nur dann, wenn das fehlschlägt, vorschlagen, mit TMethod-Typ-Hacks herumzuhacken. – Johan

+2

Vielleicht, aber ich bin mir immer noch nicht sicher, was das zugrunde liegende Problem ist, also konzentrierte ich mich auf die eigentliche Frage gestellt. Und ich verabscheue es viel mehr Zeit damit zu verbringen, dass ich schon eine Menge getan habe! –

+0

Die Antwort liefert mehr Informationen als benötigt. Kurz gesagt: Setzen Sie sich über typecast zu TMethod in die Liste, rufen Sie von der Liste über PMyEvent (listItem)^auf, wo PMyEvent =^TMyEvent. – Paul

Verwandte Themen