Tina Norris Fields
tinanfields at torchlake.com
Mon Feb 23 16:52:10 CST 2009
John, My question is why is StartTimer() a Sub and EndTimer() a Function? It is not clear to me what the distinction is between a Sub and a Function - they both look like "methods" or "functions" as found in Java. So, please explain that difference to me. Thanks. Tina jwcolby wrote: > To this point the classes we have looked at were specifically designed to allow you to “wrap” an > object that generates events and add code and variables to process those events. This lecture will > demonstrate that classes have other uses and do not have to wrap other objects. > > The class introduced today will be clsTimer, a means of timing events (things happening) in your > code. The class is perhaps the simplest class I have ever written, and perhaps the simplest class > you will ever see. > > • Click Insert / Class > • Save immediately as clsTimer > • Insert the following code into the class: > > Private Declare Function apiGetTime Lib "winmm.dll" _ > Alias "timeGetTime" () As Long > > Private lngStartTime As Long > > Private Sub Class_Initialize() > StartTimer > End Sub > > Function EndTimer() > EndTimer = apiGetTime() - lngStartTime > End Function > > Sub StartTimer() > lngStartTime = apiGetTime() > End Sub > > • Compile and save the class. > > Notice that in the header of the class we have a function definition apiGetTime that calls out to > Windows. This function gets the windows tick timer and has a resolution of 1 millisecond, or one > thousandth of a second. This simply means that we can’t time anything that takes less than one > thousandth of a second without resorting to timing it several times. It returns a long integer that > is simply an absolute number of “ticks”. Since when? It doesn’t matter, it is just “this is the > tick count RIGHT NOW”. > > To compute a “time” (and we aren’t really doing that, we are calculating a time since the first > time), you get the tick count and store it, then later you get another tick and compare it to the > first tick. The difference is the number of 1000ths of a second since the first tick count. > > Notice that we have no mInit() method in this class. Notice also that the Class_Initialize calls > the StartTimer() function. As you know now, the Class_Initialize is a class event that fires as the > class loads, so this tells the class to load the first tick time as soon as the class instance loads. > > In the header of the class we dimensioned a long variable lngStartTime. This will be used to store > the starting tick count. StartTimer() simply calls out to Windows, gets the current tick count from > Windows, and stores that count to lngStartTime. > > EndTimer() simply calls out to Windows again to get the current tick count, subtracts the current > count to the previous count stored in lngStartTime and returns that count to you the programmer. > > That’s it folks! This class has in the header a function definition to call Windows and a place to > store the count. In the body of the class it then has two methods to start the “timer” and to > return the ticks since the timer started. You are not going to see many classes simpler than that. > > So let’s discuss why we need to encapsulate this in a class. You might be saying that you can do > the same thing without the class but a class allows you to create as many of these timers as you > want. Let’s build some test code to see how this thing works and why we might need several. > > • In the tools menu click Insert / MODULE. We are building a normal module this time, NOT a class > module. > • Immediately save the module as basTimerTest > • Into this new module insert the following code: > > Function TmrTest() > Dim lngCtr1 As Long > Dim lngCtr2 As Long > Dim clsTmr1 As clsTimer > Dim clsTmr2 As clsTimer > > Set clsTmr1 = New clsTimer > For lngCtr1 = 1 To 5 > Set clsTmr2 = New clsTimer > For lngCtr2 = 1 To 100000 > Pi > Next lngCtr2 > Debug.Print clsTmr2.EndTimer > Next lngCtr1 > Debug.Print clsTmr1.EndTimer > End Function > > Function Pi() As Double > Dim dblPi As Double > dblPi = 4 * Atn(1) > Pi = dblPi > End Function > > Notice that we dim two timers, then we SET the timers on the outside of their respective loops. As > you know, the SET statement loads the class, at which point the Class_Initialize fires which grabs > the first timer tick from windows. > > The Debug.Print statement simply calls the .EndTimer method of the class and prints it to the debug > window. > > Voila, a timer, with a resolution of one thousandth of a second. > > TmrTest simulates a real world code where you have two loops, and inner loop and an outer loop. > > The inner loop times how long it takes to calculate Pi. Notice that modern computers are so fast > that I have to do it a hundred thousand times in order to get enough “tick counts” (thousandths of a > second) to even get a number to use. The outer loop simply times how long it takes to run the inner > loop 5 times. > > I have intentionally kept this thing simple, but your outer loop might time how long it takes to > read a thousand records and the inner loop might be replaced with timing how long it takes to … > transform a string from comma delimited to pipe delimited or something like that. > > In this lecture we have demonstrated that a class encapsulates all of the code required to perform > its function, plus the variables required to store its data. It also demonstrates that you can use > as many instances of the class as you need. If you need one or a hundred timers, you just dim and > SET the variables and you are off to the races so to speak. > > Classes are used to encapsulate code and data required to implement a system. You’re your > imagination is the only limit to what that system can be. > >