Posts Tagged: ‘english~english’

Event-handling with LotusScript Part II – Inheritance

18. Juni 2014 Posted by Björn Großewinkelmann

So, let's try it in English this time!

First of all, sorry for the delay - I know I've promised to get this post out to you in a weeks time when I wrote the first blog post in this series "Event Handling mit LotusScript Teil I - Persistente Event-Handler" and now it's been FOUR weeks...Sch?chtern  But to make this up to you I will publish the first blog post in English as well - let's say within the next four weeks Winken.

But now, let's get started so I can show you how event-handlers can also profit from inheritance in LotusScript!

Once you have a class that implements custom event-handlers you should know how its instances behave in case the class is part of an inheritance hierarchy. There are a couple of things you have to consider when designing inheritance hierarchies in general and inheritance with event-handlers in particular.

Flow Control

As briefly mentioned in the first part of this series: you can in fact bind multiple event-handlers to the same event. In case of Query-Events the triggering command (Open, Save, Send, Close) will only be executed if none of the bound handlers set ‘Continue’ to False. Since ‘Continue’ is declared as a Variant (which of course is a reference type) it is shared between all methods that handle the event. So if you set ‘Continue’ to True it will be true for all handlers from there on until another handler sets it to false again. Since you can’t be (reasonably) sure in which order your bound event-handlers are executed you really shouldn’t build handlers that depend on each other or use the ‘Continue’ to communicate. Fortunately this is not how inherited event-handlers work.

Inheritance

If your class overwrites an event-handler which it inherited from some base class only the child event-handler will be triggered when the event fires. The event-handler of the base class will be ignored completely. It does not matter where you bind the handler, in the base class or the child. Both times only the child event-handler will be bound.

Let’s take a look at an example (Code 1), the following code defines a controller base class:

 

Public Class UIDocControllerBase

 

           Private p_uidoc As NotesUIDocument

 

           Public Property Get UIDoc() As NotesUIDocument

                      Set UIDoc = p_uidoc

           End Property

 

           Public Sub New( pUIDoc As NotesUIDocument )

                      Set p_uidoc = pUIDoc

           End Sub

     

           Public Sub BindEvents()

                      On Event PostOpen From UIDoc Call PostOpen

                      On Event QueryClose From UIDoc Call QueryClose

                      On Event QuerySave From UIDoc Call QuerySave

           End Sub

     

           Public Sub PostOpen( Source As NotesUIDocument )

                      Print "BASE: Post Open"

           End Sub

     

           Public Sub QueryClose( Source As NotesUIDocument, Continue As Variant )

                      Print "BASE: Query Close"

           End Sub

     

           Public Sub QuerySave( Source As NotesUIDocument, Continue As Variant )

                      Print "BASE: Query Save"

           End Sub

     

           Public Sub Delete()

                      Print "Delete: UIDocControllerBase"

           End Sub

     

End Class

 

The class implements handlers for the PostOpen, QueryClose and QuerySave events. In addition it implements the BindEvents-Method which takes care of the event binding.

The following code (Code 2) defines a class CompanyUIDocController which inherits from the UIDocControllerBase class. It implements its own handlers for the QueryClose and PostOpen events, it does however not overwrite its parent’s QuerySave event-handler nor does it overwrite the BindEvents-Method.

 

Public Class CompanyUIDocController As UIDocControllerBase

     

           Public Sub New( pUIDoc As NotesUIDocument )

           End Sub

 

           Public Sub QueryClose( Source As NotesUIDocument, Continue As Variant )

                      Call UIDocControllerBase..QueryClose( Source, Continue )

                      Print "CompanyUIDocController: QueryClose"

           End Sub

     

           Public Sub PostOpen( Source As NotesUIDocument )

                      Print "CompanyUIDocController: PostOpen"

           End Sub

                       

           Public Sub Delete()

                      Print "Delete: CompanyUIDocController"

           End Sub

           

End Class

 

If you now substitute the class definition from the first blog entry of this series with the two classes of Code 1 and Code 2 and then Open, Save and finally Close the corresponding document the output will be as follows:

Fig. 1: Example output

 

Analysis

First the BindEvents-Method is called and binds the events of the NotesUIDocument to all not overridden event-handlers. That means that the PostOpen and QueryClose events are bound to the CompanyUIDocController class while the QuerySave event is bound to the base class. When we trigger the events those and only those event-handler are being executed. The QueryClose event-handler in the base class is only executed because we are explicitly calling it inside the QueryClose event-handler of CompanyUIDocController by using the “..”-notation in the function call.

     Call UIDocControllerBase..QueryClose( Source, Continue )

A call like that will always refer to the base-instance instead of the “youngest”-instance like

     Call me.QueryClose( Source, Continue )

would. And before you get any ideas both of the above calls are illegal in the event binding definition!


The only two methods which automatically call their equivalents in the base instance(s) are New and Delete. If you wish to cascade any other function calls you have to do it explicitly.
 

In conclusion, if you want to implement some functionality which is the same for all of your derived classes that code should go in the base class event-handler. On the other hand  any functionality that deals with issues specific to your current class should be located within the derived class. An example would be a base class that implements a function which forces the user to write a comment during the QuerySave event. More specific functionality like updating a parent document which is only needed on a specific form would go in the event-hander of the derived class. Just remember that you have to call the base class handler explicitly if you need the base functinality too.

If you have any more questions concerning event handling in LotusScript, please leave us a comment so we can expand this mini-series a little further.