Generic Interfaces in Delphi

Original author: Malcolm Groves
  • Transfer
Pioneer Flocks from Malcolm Groves, Generic Interfaces in Delphi.

imageMost generic examples in Delphi use a generic class. However, working on my project, I decided that I needed an interface with a generic type.

The project uses the built-in publisher-subscriber mechanism . I wanted the subscriber to have a separate Receive method for each type of event , and not a separate method with a huge case- expression that selects an action for each type of event. Also, I did not want to define an interface for each type of event. I needed a generic subscriber interface that receives the type of event as a parameter.

However, I had no idea if I could define a generic interface, not to mention the implementation. Even assuming I can do this, can Delphi choose the right Receive method to invoke? There is only one way to find out ...

Please note: in this example some parts of the code are removed, only those parts are left that are necessary to demonstrate the generic interfaces. I will talk about other parts in my next posts.

First, I described some simple events. Their content is not so interesting: Then, I defined a generic interface. This interface must be implemented by subscribers to receive events of various types. Note the type of events recorded as dzhenenrik type T .

TSomeEvent = class
// other stuff

TSomeOtherEvent = class
// other stuff

ISubscriber = interface
procedure Receive(Event : T);

Then, subscribers must implement an interface for each type of event that they want to receive. Since this is a generic interface, it is quite simple: There is no description of the ISomeEventSubscriber and ISomeOtherEventSubscriber interfaces , we can just use ISubscriber

TMySubscribingObject = class(TInterfacedObject, ISubscriber, ISubscriber)
procedure Receive(Event : TSomeEvent); overload;
procedure Receive(Event : TSomeOtherEvent); overload;

and pass the type in place. To do this, you must implement the necessarily overloaded Receive method .

The above code describes the basis of the idea. You will find the rest of the code in the corresponding test project . We implement several interfaces, each of which has strictly typed Receive events, without actually defining each of these interfaces.

And does it work? On the first try - no, it didn’t work out. No matter what type of event and through which interface I passed, the last Receive method was always executed . dunit_generic_interfaces

imageLife Rule # 37: When it comes to choosing between the confusing Malcolm and the developers of the Delphi compiler, this is probably Malcolm's mistake.

Yes, my mistake. Barry Kelly pointed out the errors of my approach. I have described a generic GUID interface . Habit. This means that ISubscriberand ISubscriber, and any other interfaces defined from this generic will have the same GUID . Together with using the " as " operator to get a link from an instance of TMySubscribingObject , this confused Delphi and made us always return the same interface link.

I removed the GUID and " as " - everything worked fine.

In future posts, I’ll show other parts: the publisher and the Event Broker. An interesting side effect of determining the events that the class is interested in is that the event broker can simply check the interfaces implemented by subscribers to find out which events they are subscribed to.

You can help improve the translation.
Translation: © r3code.

Also popular now: