Presently there does not exist a common understanding on how to support event/signal notification (callbacks) in modern object-oriented programming languages.
In the course of the Java development Sun Microsystems has replaced the original event handling concept by a new philosophy based on event listeners, adapter classes, and Java language extensions introducing anonymous and inner classes.
Microsoft has made (and withdrawn) a proposal for an own callback-specific Java language extension ("delegates"), and has then provided a more comprehensive delegate or callable entity notion in C#.
The problem is primarily to find a truly object-oriented and type-safe way to associate arbitrary "client data", provided by the envisaged callback receiver, with the event/signal sender object ("server") without requiring the signal sender to "know" the type and structure of the client data.
We felt that the present Java and C# solutions are too complex and indirect and lack the desirable intuitive simplicity and clarity. In contrast to the former, the Lava solution doesn't require the introduction of additional types of entities (like delegates or inner classes) but is solely based on three specific executable statements: connect, disconnect and signal.
The principal idea has been taken over from the signal/slot concept in TrollTech's Qt toolkit, and has been modified and adapted to the conceptual setting of the Lava language:
In the signal sender class a signal (that can be emitted by an object of this class) is declared as a member function without output parameters, having the special "signal" attribute. A signal function doesn't have an implementation. An object of a class having signals may explicitly emit a signal using the signal statement (instead of a normal function call statement), with actual parameters, say parm1, parm2, ... :
| signal self.sigFunc (parm1,parm2,...) |
Note that an object (self in the example) can only itself emit a signal; it cannot force another object to emit a signal, except, of course, if the class of the other object exports a method having this effect (like the sendSignal function in our callback sample).
You can use the connect statement to specify to which handler objects and handler methods a signal is to be transmitted:
| connect sigSender.sigFunc to handlerObj.hdlFunc |
You may connect the same signal sender / signal function to several handler objects / handler functions. When the sender emits this signal, then all handlers will be invoked in the order of the corresponding connects
Transmitting a signal to a handler object handlerObj having a handler method hdlFunc means that the handler function is invoked with that handler object as call object, and the actual parameters are taken from the signal statement, just as if the following function call would be performed in place of the signal function call:
| call handlerObj.hdlFunc(parm1,parm2,...) |
This requires that the handler function must have the same number of input (and no output) parameters, and the formal parameters of the signal function must be assignment compatible to the corresponding formal parameters of the handler function.
Moreover, if the call objects or the formal parameters of the functions occurring in the connect statement depend on virtual types, then LavaPE will reject the connect if sigSender and handlerObj don't belong to the same pattern context and thus don't apply the same interpretation to the involved virtual types.
The envisaged extension of the Lava GUI support requires that you can also specify a signal sender class only in the connect statement, rather than a concrete signal sender object (to be explained after the GUI support extension.)
See also our callback sample.