.Net Code Monkey RSS 2.0
 Wednesday, April 09, 2008

Outline

Background

You may wonder why write an article on classes in VBScript when there are hundreds of articles already on the web about classes? Well, it's because when I first tried to learn about classes I found it hard to visualise and to "get my head around" the concept of using classes let alone finding basic articles showing how to use them within ASP VBScript.

What I hope to acheive with this article is to provide the reader with a basic understanding of classes in a manner that a complete novice programmer, like my self at the time, would find useful and easy to follow. I also hope to provide a first insight into a more object-orientated programming (OOP) approach in VBScript.

Introduction

So what is a class? A class is basically the coding framework we need to enable an object to be created at runtime. A class it's self does not represent any thing, but the object it lets us create can represent any element or entity that we choose, from a real world object like a car, to a virtual object like an XmlCreator for creating XML data files. A class also allows us to encapsulate any code directly relating to the object we wish to create, and abstract this code out of the "presentation layer" (the page HTML).

In our example we are going to create a class which when instantiated will create an object that will represent a car. The code inside the class is split into two main areas; Properties and Methods. A property is a thing that is owned and in a class we treat one exactly as we would a variable. A method is a way of carrying out an action, possibly on values held in the properties, and you will be familiar with these as Functions or Sub Procedures.

In our car example some properties we may have are:

  • Number of wheels
  • Colour of paint
  • Is engine running?
  • Is clutch engaged?
  • Current selected gear

Some of the methods we may have are:

  • Start engine
  • Stop engine
  • Depress Clutch
  • Release Clutch
  • Select gear

So now we have a basic outline of what a class is let's create one!

Creating our first class

Open your favourite text editor / developement tool, create a new file, save it as classCar.asp and enter the following two lines between the script tags.

<%
Class Car

End Class
%>
"Class Car" defines the name of the class much in the same way that you would define a method "Function AddTax()" but without the parenthesis.  As you will no doubt expect "End Class" defines the end of the class, again as you would with a sub or function; "End Sub". With these two lines created we could create our car object using this class in the code of a page, but as there is no functionality within the class yet we will save that for a little later.

Defining Properties

Next we need to define some properties for the object we wish to create but before we can do that we need to define some member level fields to hold the values for the properties. Add the follwing declarations into the top of the class.

<%
Class Car

    'Member level fields
    Private m_intNumberOfWheels 'As Integer
    Private m_intCurrentSelectedGear 'As Integer
    Private m_strColourOfPaint 'As String
    Private m_blnIsEnfgineRunning 'As Boolean
    Private m_blnIsClutchEngaged 'As Boolean

End Class
%>

I have used an "m_"  prefix to my variable names to signify that they are defined at member level, the same level as the properties and methods for the class. You may wish to define your fields with a more current way of thinking as just "_" or maybe without. (Your choice entirely but I found at the time that it helped me keep track of the scope of my variables!) I have also declared the field as "Private" as I do not want them to be "visible" from out side my class. I.e. the page the instantiates the class has no access to these fields.

Now we are going to declare a property for the "Number of wheels"

'Properties
 Public Property Get NumberOfWheels()
     NumberOfWheels = m_intNumberOfWheels
 End Property
 Public Property Let NumberOfWheels(ByVal Value)
     m_intNumberOfWheels = Value
 End Property

You can see that there are two parts to our "Number of wheels" property the first "Get" allows us to retrieve the value stored in it and the second allows us to populate the property with a value.  You can see that I have declared both parts of the property as "Public" as I do want this property to be visible from out side the class. Each part of the property is declared just as you would a Function or Sub, along with "End Property" to define the end of the properties functionality. I say functionality, because unlike the static fields that we have declared at the top of the class, a property can hold functionality just like a Sub or Function. At present all the "Get NumberOfWheels" property does return the value held in our m_intNumberOfWheels field. The "Let NumberOfWheels" property allows us to populate the m_intNumberOfWheels field with a value.

Lets add the rest of the properties and see what the code looks like so far.

<%
Class Car

    'Member level fields
    Private m_intNumberOfWheels 'As Integer
    Private m_intCurrentSelectedGear 'As Integer
    Private m_strColourOfPaint 'As String
    Private m_blnIsEngineRunning 'As Boolean
    Private m_blnIsClutchEngaged 'As Boolean

    'Properties
    Public Property Get NumberOfWheels()
        NumberOfWheels = m_intNumberOfWheels
    End Property
    Public Property Let NumberOfWheels(ByVal Value)
        m_intNumberOfWheels = Value
    End Property

    Public Property Get CurrentSelectedGear()
        CurrentSelectedGear = m_intCurrentSelectedGear
    End Property
    Public Property Let CurrentSelectedGear(ByVal Value)
        m_intCurrentSelectedGear = Value
    End Property
   
    Public Property Get ColourOfPaint()
        ColourOfPaint = m_strColourOfPaint
    End Property
    Public Property Let ColourOfPaint(ByVal Value)
        m_strColourOfPaint = Value
    End Property
   
    Public Property Get IsEngineRunning()
        IsEngineRunning = m_blnIsEngineRunning
    End Property
    Public Property Let IsEngineRunning(ByVal Value)
        m_blnIsEngineRunning = Value
    End Property

    Public Property Get IsClutchEngaged()
        IsClutchEngaged = m_blnIsClutchEngaged
    End Property
    Public Property Let IsClutchEngaged(ByVal Value)
        m_blnIsClutchEngaged = Value
    End Property
   
End Class
%>

Now we have some properties for the class we need to create some methods to hold functionality.

Adding functionality

So far we have created a class, defined some private fields to hold values, some public properties to access these values and now we need to add some methods to provide functionality in the class and to work with these values. Methods within a class are written in the same format as you would write one normally within the ASP code of your page, however it is wise to take care of the scope (Public/Private) of the method to restrict it's access from out side of the class where necessary. Anyway, before we start adding our own functionality, willy-nilly, there are two important methods we must first take a look at.

Initialisation and Termination methods

Any code that is present within the "Sub Class_Initialize" method will be fired upon instanciation (creation) of the object. Any code that is present in the "Sub Class_Terminate" method will fire just before the object is destroyed. The "Initialize" method is very useful for instanciating other objects or populating fields with values as soon as the object is created. The "Terminate" method can be used to ensure that any objects instanciated within the class are disposed of correctly before the class is destroyed.

In our Car example we are just going to instanciate the state and values of a few of our private member fields. Add the following code below the class properties.

'Class Initialisation and Termination
 Sub Class_Initialize()
     m_intNumberOfWheels = 4
     m_intCurrentSelectedGear = 0
     m_strColourOfPaint = "Blue"
     m_blnIsEngineRunning = False
     m_blnIsClutchEngaged = True
 End Sub
 Sub Class_Terminate()
 '
 End Sub

As you can see we have given our car 4 wheels, the colour is blue, we have set the current gear as neutral (well zero!), and the engine is not running and the clutch is engaged.

Right, so now lets give our car some functionality! Add the following methods below the first two.

'Public methods
 Public Sub StartEngine()
     If (m_intCurrentSelectedGear = 0) Or (m_blnIsClutchEngaged = False) Then
         m_blnIsEngineRunning = True
         Response.Write "<p>The engine started."
     Else
         Response.Write "<p>You cannot start the engine if car is in gear unless clutch is dis-engaged!"
     End If
 End Sub
 
 Public Sub StopEngine()
     m_blnIsEngineRunning = False
     Response.Write "<p>The engine stopped."
 End Sub
 
 Public Sub DepressClutchPedal()
     m_blnIsClutchEngaged = False
 End Sub
 
 Public Sub ReleaseClutchPedal()
     m_blnIsClutchEngaged = True
 End Sub
 
 Public Sub SelectGear(ByVal gearNumber)
     If IsNumeric(gearNumber) Then
         If (gearNumber > -1) And (gearNumber < 6) Then
             If (m_blnIsClutchEngaged = False) Then
                 m_intCurrentSelectedGear = gearNumber
                 Response.Write "<p>You selected gear #" & gearNumber
             Else
                 Response.Write "<p>You must select dis-engage the clutch to select a gear"
             End If
         Else
             Response.Write "<p>You car doesn't have that gear!"
         End If
     End If
 End Sub

We are not really worried about what the actions of the methods are more just to show how they are implemented into the class. The next step is to build a page with that will use our class to create a car object.

Build a page

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<%Option Explicit%>
<!-- #Include File="classCar.asp" -->
<html>
<head>
<title>Asp Class Example</title>
</head>
<body>
<%
Call RenderCar()
%>
</body>
</html>

<%
Private Sub RenderCar()
   '
End Sub
%> 

Instanciating an object

The first thing you should notice that we reference the class file by using the "#Include File" method. This "imports" the code from our class file into our page. In the RenderCar method add the following code, then we'll go through it bit by bit.

 Dim MyCar 'As Car
 Set MyCar = New Car

 Response.Write "<p>My car's colour is " & MyCar.ColourOfPaint
 Response.Write "<p>My car has " & MyCar.NumberOfWheels & " wheels"
 Response.Write "<p>If I now paint my car red..."
MyCar.ColourOfPaint = "Red" Response.Write "<p>My car's colour is now " & MyCar.ColourOfPaint With MyCar .StartEngine() .SelectGear(6) .SelectGear(1) .DepressClutchPedal() .SelectGear(1) .ReleaseClutchPedal() .StopEngine() .StartEngine() .DepressClutchPedal() .StartEngine() .StopEngine() End With If Not(MyCar Is Nothing) Then Set MyCar = Nothing End If

Now breaking it down into bite sized chunks... First we declare a new variable "MyCar" to hold an instance of our "Car" object and then set the variable to reference a newly created instance of that object. Note the syntax for setting the reference; unlike setting a value of an integer where we would use intThis = 12, we must use the Set word so Set ThisVariant = ThatObject.

Dim MyCar 'As Car
Set MyCar = New Car

As we used the "Sub New" method in the class to populate some values into the properties as soon as we instanciate the object we can retrieve them right away with... [MyObjectName].[PropertyName] in this case MyCar.ColourOfPaint and MyCar.NumberOfWheels.

Response.Write "<p>My car's colour is " & MyCar.ColourOfPaint
Response.Write "<p>My car has " & MyCar.NumberOfWheels & " wheels"

Now we can change the value of one of our objects properties with [MyObjectName].[PropertyName] = Value. In this case we will change the paint colour to red. MyCar.ColourOfPaint = "Red" and then display the value of the property as before.

Response.Write "<p>If I now paint my car red..."
MyCar.ColourOfPaint = "Red"
Response.Write "<p>My car's colour is now " & MyCar.ColourOfPaint

Next we will call some of the methods of the object.  To do this we use [ObjectName].[MethodName]. Also to make the code clearer to read you can use With [ObjectName] and End With blocks. This saves writing out [ObjectName].[MethodName] for each method call. Then you just need to use dot[MethodName] or dot[propertyName]

With MyCar
     .StartEngine()
     .SelectGear(6)
     .SelectGear(1)
     .DepressClutchPedal()
     .SelectGear(1)
     .ReleaseClutchPedal()
     .StopEngine()
     .StartEngine()
     .DepressClutchPedal()
     .StartEngine()
     .StopEngine()
End With

I wont go into the details of what each method does as this should be clear from the method name. What is important is how you access the methods from the page. Please note that any class methods that were declared Private will not be available for use on the page.

Last of all we have to dispose of the object properly to release the memory that the object resided in.

If Not(MyCar Is Nothing) Then
     Set MyCar = Nothing
End If

We do this by setting the variable that references the object to reference of Nothing (after of course, checking it was set in the first place).

Multiple instances on one page

So what if we need to have multiple instances on one page? Well all we need to do is declare a different variable to reference each instance.

Dim MyCar 'As Car
Dim YourCar 'As Car
Set MyCar = New Car
Set YourCar = New Car
MyCar.ColourOfPaint = "Black"
YourCar.ColourOfPaint = "White"
Response.Write "<p>My car's colour is " & MyCar.ColourOfPaint
Response.Write "<p>Your car's colour is " & YourCar.ColourOfPaint

You can have as many instances on the page as you like, but each must be referenced from a variable. Try it and see. Remember to clear up all your objects at the end by setting all their references to nothing.

I hope this gives many novice programmers who have not yet used classes in classic asp the inspiration to get on and try it. To me when I started using them it seemed like a lot of effort for what seemed very little gain. But there are many advantages to programming this way, code maintenance of my apps is now much less troublesome, with it being a lot easier to add additional functionality. The code in the pages are now easier to read through as there is little "business logic" embedded within in them, and with all my classes in one folder its easy to find the relevant class and copy it to a new aplication, so developing new applications is getting much quicker. Lastly, but not least is that the transition to ASP.Net if you choose to do it later, will be a little smoother.

Hopefully in the not to distant fututre I will publish an article on using objects wrapped up inside a dictionary object as an alternative to bringing a recordset back to your page or to using GetRows() and arrays. It will also use a dataAccess class to abstract the dataAccess out of the business logic, and get a tiny bit closer to the 'N' tier programming approach.

A point to note

Although in this case I have used Response.Write within the class to output a result, in practice this is not a good idea. One of the advantages of using classes is to abstract out the "Business Logic" of the page from the "Presentation Code" (html) so it is much better practice to populate a property with the results of your method calls and retrieve the value from the property as shown with Response.Write MyCar.ColourOfPaint in the above example.

Please note this is in fact a reprint of the "Classic ASP - Introduction to VBScript classes" article I wrote for Developer Fusion a while back. Thanks for reading this, I hope some of you find it useful. Your comments, good or bad, are as always, very welcome as this was my first ever article.

Wednesday, April 09, 2008 7:27:22 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Classic Asp | VB Script | Object Orientation | Classes
Archive
<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
Blogroll
 Clemens Vasters
 Harry Pierson
Passion * Technology * Ruthless Competence
 Joshua Flanagan
A .NET Software Developer
 Michael Schwarz's Blog
Developing applications on the Microsoft platform since Windows 3.1!
 Omar Shahine
Yet another Microsoft blogger
 Scot GU
Scott Guthrie lives in Seattle and builds a few products for Microsoft
 Scott Hanselman
Programming Life and the Zen of Computers
 Tom Mertens
Tom's corner
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Duane Wingett
Sign In
Statistics
Total Posts: 32
This Year: 6
This Month: 1
This Week: 1
Comments: 35
Themes
Pick a theme:
All Content © 2010, Duane Wingett
DasBlog theme 'Business' created by Christoph De Baene (delarou)