Tech Note 29: Working with Classes

August 19, 2006

© NSB Corporation. All rights reserved.

Contributed by Ricardo Carraretto

VBScript supports the concept of objects and allows us to define classes and create instances, however it does not support the concepts of inheritance or polymorphism. Because of this rescriction, it is known as Object Based rather than fully Object Oriented. Despite this restriction, it is possible to simulate some level of inheritance using a technique called delegation which will be presented in the topics below.

1. Defining Classes

A class is defined in VBScript using the Class statement, like this:
Class Foo

   Private FooAttribute

   Public Sub FooSub()
      MsgBox "Foo.FooSub"
   End Sub

   Public Function FooFunction()
      MsgBox "Foo.FooFuncion"
      FooFunction = "value"
   End Function

End Class
This defines a new class called Foo with an attribute called FooAttribute. Since it was declared using the keyword Private, it will only be visible to the methods inside the class. If you want to make an attribute accessible outside the class, consider using the keyword Public. It is good programming practice to keep attributes as Private and use Properties to access them. This would allow the data to be checked before being set or read.

2. Creating Instances

To create an object instance in VBScript we need to use both Set and New keywords. It is also good practice to declare the variables with the Dim keyword as required by Option Explicit.
Dim objFoo
Set objFoo = New Foo
This creates an instance of the class declared in the previous section and assigns it to the objFoo variable.

3. Sending Messages

Messages are sent to instances using the dot notation.
Dim myValue
objFoo.FooSub()
myValue = objFoo.FooFunction()
MsgBox "myValue = " & myValue
The two methods declared in the class definition are called, in the first case there is no return value(a Sub), in the second we assign the return to the variable myValue (a Function).

3. Properties

One good way to use the data hiding and checking attributes values is the Property concept:
Class Foo

   Private i_FooAttribute

   Public Property Let FooAttribute(byVal Param1)
      ( ... code to check attribute value compliance ... )
      i_FooAttribute = Param1
   End Property
   
   Public Property Get FooAttribute
      ( ... code to format attribute output ... )
      FooAttribute = i_FooAttribute
   End Property
   
End Class

5. Inheritance and Polymorphism

VBScript as a language does not provide any inheritance mechanism nor any mechanism for polymorphism. However it is possible to have some kind of inheritance by using a technique called delegation. This simply means that we define an attribute of the sub class to be an instance of the theoretical parent class. We then define a method for all of the "inherited" methods which simply calls (or delegates to), in turn, the method of the parent instance. Let's subclass Foo as defined above:
Class SubFoo

   Private parent

   Private Sub Class_Initialize()
      Set parent = New Foo
   End Sub

   Public Sub FooSub()
      parent.FooSub
   End Sub

   Public Function FooFunction()
      FooFunction = parent.FooFunction
   End Function

   Public Sub SubFooSub
      MsgBox "This is unique to the SubFoo class"
   End Sub

End Class

Dim objSubFoo, value
Set objSubFoo = New SubFoo
objSubFoo.FooSub
value = objSubFoo.FooFunction
objSubFoo.SubFooSub
MsgBox "Value = " & CStr(value)
The catch is the link made between the attribute parent and the "parent class". This is automatically done when an object of class SubFoo is instantiated, because of SubFoo's constructor, defined by the special private method Class_Initialize. The constructor and destructor concepts are shown below.

6. Constructors and Destructors

VBScript provides support for the constructor concept through the Class_Initialize method. This method is private, allows no parameters and is called automatically when a new instance of the class is created. A call to the New keyword calls the Class_Initialize method, if it exist.

We can use a Function as a workaround to the parameters restrictions on Class_Initialize:

Function NewFoo(Param1, Param2, ...)
  Dim myFoo
  myFoo = New Foo
  myFoo.attr1 = Param1
  myFoo.attr2 = Param2
  ( ... additional initialization steps ... )
  Set NewFoo = myFoo
End Function

To have a method automatically called when and object is destructed, use the Class_Terminate() method:

Class Foo

  ( ... class code ... )

  Sub Class_Terminate()
    ( ... cleanup code ... )
  End Sub

End Class

7. Conclusion

Working with classes can dramatically improve the application development cycle, as it becomes possible to encapsulate data and the logic to handle this data in the same container.

Despite the lack of support on inheritance and polymorphism, the rest of OO support is very stable and it will provide whole new world to write complex applications in NS Basic/CE.