2016-09-01 2 views
2

Есть ли общий предок для делегатов Delphi, которые объявлены с предложением of object?Общим предком для делегатов объекта в Delphi

Мне нужно найти общий предок для TNotifyEvent и мой пользовательский делегат:

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

сделать универсальный метод для стрельбы этих событий.

Должен ли я использовать указатель? или TObject?

+0

Можете ли вы привести пример того, что вы пытаетесь сделать. Сейчас кажется, что вы пытаетесь стрелять в ногу, вызывая методы, не поставляя все необходимые параметры. – Johan

+1

Я думаю, что вы ошибаетесь, полагая, что 'процедура (отправитель: TObject) объекта' и' procedure (Sender: TObject; xyz: TSomehting) объекта' каким-то образом совместима. Они не! Если у вас нет правильной подписи при вызове, вы передадите неправильные параметры, заканчивающиеся неудачей. – Johan

+0

Я хотел бы предложить решение с использованием дженериков. Но у меня недостаточно информации, чтобы сформулировать полный ответ. Вы пытаетесь сделать «TList », который вы можете вызвать; это то, что вы пытаетесь сделать? Если это так, у меня есть легкий ответ на эту проблему. – Johan

ответ

6

Вам необходимо спуститься и загрязниться деталями реализации для method pointers. Они хранятся в виде так называемого двойного указателя. Один указатель на объект вызова метода (экземпляр) и один указатель на сам метод (код).

Вы можете использовать тип TMethod от блока System для представления указателей методов. Его заявление выглядит так (с операторами сравнения удалена для простоты):

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

Вы должны использовать приведение типа, чтобы сделать задание между этими типами:

uses 
    System.Classes; 

var 
    Event: TNotifyEvent; 
    Method: TMethod; 

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

Очевидно ничего из этого не является типобезопасным поэтому вам необходимо обеспечить правильность. Компилятор вам не поможет. Для работы с указателями методов нет ничего похожего на операцию преобразования проверенного типа, as. То есть, вам решать, что, когда вы отбрасываете от TMethod к типу указателя конкретного метода, вы должны убедиться, что экземпляр TMethod действительно является экземпляром типа указателя метода, к которому вы добавляете. Подумайте о том, что весь этот процесс аналогичен кастингу от типизированного указателя на нетипизированный указатель, а затем обратно.

Теперь, если вы собираетесь хранить произвольные указатели методов в экземплярах TMethod, это нормально. Но что происходит, когда вам необходимо запустить эти методы. Вам нужно знать, какой тип указателя метода действительно находится за каждым экземпляром TMethod. Чтобы вы знали, как его использовать, какие аргументы ему нужны, и так, как это назвать. Это означает, что вам нужно хранить дополнительную информацию об истинном типе метода, наряду с самим сырым методом.

Итак, я думаю, что, возможно, я ответил на вопрос, который вы задали, но я не уверен, что это будет очень полезно для вас. Чтобы понять, что я думаю, нам действительно нужно знать больше о том, чего вы пытаетесь достичь, и какую информацию у вас есть, когда.

Например, если вы знаете аргументы, которые должны быть переданы методу в то время, когда вам нужно его хранить, вы можете использовать захват переменной и обернуть его анонимным методом. Это позволит вам сохранить безопасность типов и избежать любых довольно сомнительных бросков, которые я демонстрирую выше. Возможно, вам понадобится partial application, как средство адаптации ваших неоднородных указателей методов к одному и тому же интерфейсу. В этом случае снова могут помочь анонимные методы.

+0

Да, это правильно. Esp в свете безопасности типа, я думаю, у вас есть ответ вокруг назад. Сначала вы должны сначала начать с типа безопасного варианта, и только если это не поможет, вы можете нападать на хакеры типа TMethod. – Johan

+2

Возможно, но я до сих пор не уверен, в чем заключается основная проблема, поэтому я сосредоточился на самом заданном вопросе. И я не хочу тратить на это гораздо больше времени, уже потратив немало денег! –

+0

В ответе содержится больше информации, чем требуется. Вкратце: поместите в список через typecast в TMethod, вызовите из списка через PMyEvent (listItem)^где PMyEvent =^TMyEvent. – Paul

Смежные вопросы