Обобщенные интерфейсы в Delphi Большинство примеров использования дженериков в Delphi используют класс с дженерик-типом. Однако, работая над своим проектом, я решил, что мне нужен интерфейс с дженерик-типом. В проекте используется встроенный механизм издатель-подписчик. Я захотел чтобы подписчик имел для каждого типа события отдельный метод Receive, а не отдельный метод с огромным case-выражением, выбирающим действие для каждого типа события. Также я не хотел определять интерфейс для каждого типа события. Мне был нужен дженерик интерфейс подписчика, который получает тип события, как параметр. Однако, я понятия не имел, могу ли я определить дженерик интерфейс, не говоря уже о реализации. Даже если предположить, что я могу сделать это, сможет ли Delphi выбрать правильный метод Receive для вызова? Есть только один способ узнать ... Обратите внимание: в этом примере убраны некоторые части кода, оставлены лишь те части, которые необходимы для демонстрации дженерик интерфейсов. О других частях я расскажу в своих следующих сообщениях. Сперва я описал несколько простых событий. Их содержание не так интересно: TSomeEvent = class // прочее end; TSomeOtherEvent = class // прочее end; Затем, я определил дженерик интерфейс ISubscriber = interface procedure Receive(Event : T); end; Этот интерфейс должен быть реализован подписчиками для получения событий разного типа. Заметьте, тип событий записан как джененрик тип . Затем, подписчики должны реализовать интерфейс для каждого типа событий, которые они хотят принимать. Поскольку это дженерик интерфейс - это довольно просто: TMySubscribingObject = class(TInterfacedObject, ISubscriber, ISubscriber) protected procedure Receive(Event : TSomeEvent); overload; procedure Receive(Event : TSomeOtherEvent); overload; end; Здесь нет описания интерфейсов ISomeEventSubscriber и ISomeOtherEventSubscriber, мы можем просто использовать ISubscriber и передать тип на месте. Для этого нужно реализовать обязательно перегруженный метод Receive. Вышеприведенный код описывает основу задумки. Остальной код вы найдете в соответствующем тестовом проекте. Реализуем несколько интерфейсов, каждый из которых имеет строго типизированные Receive события, без определения каждого из этих интерфейсов фактически. И это работает? С первой попытки - нет, не получилось. Независимо от того, какой тип события и через какой интерфейс я передавал, всегда выполнялся последний метод Receive. dunit_generic_interfaces Жизненное правило №37: Если речь идет о выборе между запутывающимся Малькольм и разработчиками компилятора Delphi, вероятно, это ошибка Малькольма. Да, моя ошибка. Барри Келли указал на ошибки моего подхода. Я описал дженерик интерфейс с GUID. Привычка. Это означает, что ISubscriber и ISubscriber, и любые другие интерфейсы определенные с этого дженерика будут иметь одинаковые GUID. Вместе с использованием оператора "as" для получения ссылки из экземпляра TMySubscribingObject, это путало Delphi и заставляло всегда возвращать одну и туже ссылку на интерфейс. Удалил GUID и "as" - все заработало замечательно. В будущих сообщениях покажу другие части: издателя и Брокера событий. Интересный побочный эффект определения событий, которыми интерисуется класс, в том, что брокер событий может просто проверить интерфейсы реализованные подписчиками, чтобы узнать на какие события они подписаны. ------------------------------------------------------------------------------- http://translated.by/you/generic-interfaces-in-delphi/into-ru/trans/ Original (English): Generic Interfaces in Delphi (http://www.malcolmgroves.com/blog/?p=420) Translation: © r3code. translated.by crowd