HTML5, CSS3, jQuery, JSON, Responsive Design...

Multiple constructors for LotusScript objects

Michael Brown   September 10 2011 12:36:22 AM


Java allows you to have multiple constructors for your classes, as long as each one has a different "signature", i.e, a different list of parameters and/or parameter types.

LotusScript allows you only one object constructor, which must be called Sub New.  You can, however, begin to approximate Java's multi-constructor functionality by declaring a your Sub New's parameter as a variant.  You can then then use the TypeName function to identify what kind of data type the variant really is and so call different construction code accordingly.

Below is an example class, ExtendedNotesNameClass, where I use this technique to extend LotusScript's built-in NotesName class.  (I say "extend" although you can't extend the built-in classes in Domino; you can only wrap them, which is what I've done via the m_NN class variable.)  I want to able to instantiate this class by passing in a Notes name as either a string or as a built-in NotesName LotusScript object.  You can see how I've used TypeName to handle both eventualities.

(FYI, I created the class in order to house the AbbreviatedReally function, now a method, of course.  What this method does is strip the @ part off if the address is a Notes-style address, but not if it's an internet-style address.  The Abbreviated property of the built-in NotesName class leaves this on, e.g. Michael Brown/IT/Acme@acme.  I want the "@acme" part to be stripped off in this case.)
'libExtendedNotesNameClasses:

Option Public
Option Declare

Public Class ExtendedNotesNameClass
        ' Adds some extra stuff to the built-in NotesName class
        Private m_NN As NotesName
       
        Sub New (parameterObj As Variant)
                Dim parameterType As String
                parameterType = Typename(parameterObj)
                Select Case Lcase(parameterType)
                Case "notesname":
                        Set Me.m_NN = parameterObj
                Case "string"
                        Set Me.m_NN = New NotesName(parameterObj)
                End Select
               
        End Sub
       
        Public Property Get NN As NotesName
                Set NN = Me.m_NN
        End Property
       
        Public Property Get AbbreviatedReally As String
                ' Returns a portion of the address that's *really* abbreviated.  That is, for a Notes-style address, we only
                ' want what's to the left of the @ sign, if there is one.  If it's an internet-style address, then we want the
                ' whole thing, of course.
                If Me.m_NN.Organization <> "" Then                ' If it has an Organization property then it's a Notes-style email address
                        If Instr (Me.m_NN.Abbreviated, "@") > 0 Then
                                AbbreviatedReally = Strleftback(Me.m_NN.Abbreviated, "@")
                        Else
                                AbbreviatedReally = Me.m_NN.Abbreviated
                        End If
                Else                ' an internet-style address is easier
                        AbbreviatedReally = Me.m_NN.Abbreviated                        
                End If
        End Property
       
End Class



This only gets me so far, however.  I am still restricted to passing in only one parameter to your constructor.  Wouldn't it be nice if I could pass in a different number of parameters, and of different types and have my constructor handle them?  Impossible in LotusScript?  Watch this space!







Comments

1Erik Brooks  09/10/2011 8:21:44 PM  Multiple constructors for LotusScript objects

You could pass an array of variants... that should be a valid parameter when a variant is expected.

2Peter Presnell  09/10/2011 10:52:11 PM  Multiple constructors for LotusScript objects

This topic is covered in the Lotus Notes and Domino developers wiki. { Link }

3Mike Brown  09/11/2011 2:02:39 AM  Multiple constructors for LotusScript objects

@Peter,

Thanks for the link. I actually found that not long after making my own post. (Der, should have looked first.)

I have in mind something slightly different....

@Erik,

Yes, an array of variants would work.

You would still have the disadvantage of having to get the members of the array in the right order though. And whenever you changed that in the class constructor, you'd likely have to update all your calling functions accordingly too.

What I've got in mind is more like how you can do it in JavaScript { Link }

4Ethann Castell  09/12/2011 9:11:15 PM  Multiple constructors for LotusScript objects

The best way to get around this is to pass a structure (or class containing only member vars) to the constructor.

This gets around the need for specific ordering of parameters in the array.

5Mike Brown  09/12/2011 10:06:43 PM  Multiple constructors for LotusScript objects

@Ethann,

Just exactly what I had in mind. It's how I handle it in JavaScript already: { Link }

Sadly though, you can't create LotusScript objects on the fly like you can JavaScript objects. The object parameter passed to the constructor would need to have its own Class definition. That's a fair bit of work to set up, but it would get around the problem of needing multiple parameters, passed in a particular order.

6Lars Berntrop-Bos  09/13/2011 8:58:23 AM  Multiple constructors for LotusScript objects

But you can. That's how dynamic classloading works.

See: { Link } Object Oriented Lotusscript presentations

7Mike Brown  09/13/2011 9:46:42 PM  Multiple constructors for LotusScript objects

@Lans,

Many thanks for that link. I'd read Bill's work on OO LotusScript before, but had missed the slides concerning Dynamic Loading... or maybe I read them and didn't understand them!

In fact, I'm not sure now I completely understand how it works, but work it does.

8Lars Berntrop-Bos  09/14/2011 5:08:06 AM  Multiple constructors for LotusScript objects

It works by constructing code in runtime, and use s an Execute statement to run the construct. When used for objects, the first time it's constructed there is a performance hit when the code is compiled, after that it runs full tilt.

If you really want to expand your mind, check out Alain Romedenne's work. He has figured out a way to use the classes fully typed instead of as variants, so if you use the classes elsewhere you get compiler checks (Option Declare) benefits.

Read: { Link }

He has other easily implemented methods in his blog which can be very valuable: use of a certain way of declaration, you can make your code more robust by implementing static globals.

9Mike Brown  09/14/2011 7:16:19 PM  Multiple constructors for LotusScript objects

@Lars

Thanks for again for the link.

I read through Alain's stuff briefly, and suffered a severe brain explosion, I'm afraid. I like his technique for creating Abstract classes, but how he's applying it to his Factory stuff is completely beyond my chops.

It also seems include a lot of scary-looking stuff that's specific to what versions of Notes you happen to be using, e.g:

LotusScript.lang.R3.Interpreter

LotusScript.lang.R4.Interpreter

and so on. And none of that stuff goes beyond version 5.

The BIll/IBM technique does what I want and I understand how it works. That's good enough for me. Compiler-time checking I can do without. Come to think of it, compiler-time checking is what led to a lot of my problems in the first place!!!

10Lars Berntrop-Bos  09/15/2011 2:41:14 AM  Multiple constructors for LotusScript objects

Yes that was my first reaction too. What he has really done is refine the dynamic class loading technique so that instead of all variants you can have compile time type checks instead of runtime.

What you call the scary looking stuff is part of this particular implementation, a timekeeping class which can be run on a lot of platforms and hides the implementation differences, and solves running on different platforms by dynamically loading different implementations of the same interface. Also note that the R3 and R4 you mention are LotusScript versions. Those have a relation with the Notes version, but are not the same.

Don't disparage compiler time checking too much. If they cannot be done, LotusScript must use variants. That carries a significant performance penalty, as detailed in the same redbook that discusses dynamic classloading: Performance considerations for Domino Applications: { Link }

So: for large systems/frameworks it is certainly worth it to explore these techniques. Another I just came across while looking into this is the use of Get/Set Property in ScriptLibraries, outside of a class. This gives you the opportunity to have globals which cannot be easily corrupted by a sloppy program. Examples here: { Link } and here: { Link }

About