Introduction.
Last week, we created a derived Class, 'lsVolume'
, using ClsArea
as the base class. In that approach, we added property procedures in the derived class to expose the base class’s properties and functions to the user programs. This method, however, requires repeating all the base class property procedures in the derived class.
In this section, we will explore how to create the same derived ClsVolume
class without duplicating the property procedures of the ClsArea
base class.
So far, we have learned about Get and Let property procedures in classes. There is also a third type: the Set Property Procedure, which is used to directly assign an object to a class object of the same type.
Before proceeding, you may want to revisit the earlier pages on this topic if you haven’t already. Links are provided below:
- MS-Access Class Module and VBA
- MS-Access VBA Class Object Arrays
- MS-Access Base Class and Derived Objects
ClsVolume Class, the Makeover.
We shall create a different variant of the same ClsVolume Class Module we created last week, using ClsArea as Base Class, with a different approach, and with less Code.
Create a new Class Module and change its Name Property Value to ClsVolume2.
Copy and Paste the following Code into the Class Module ClsVolume2 and Save the Module:
Option Compare Database Option Explicit 'Method two-1
Private p_Height As Double Private p_Area As ClsArea Public Property Get dblHeight() As Double dblHeight = p_Height End Property Public Property Let dblHeight(ByVal dblNewValue As Double) p_Height = dblNewValue End Property Public Function Volume() As Double Volume = p_Area.dblLength * p_Area.dblWidth * p_Height End Function
The new Get and Set Property Procedure for the ClsArea Object.
Public Property Get CArea() As ClsArea Set CArea = p_Area End Property Public Property Set CArea(ByRef AreaValue As ClsArea) Set p_Area = AreaValue End Property
From the Debug menu, select Compile [Project Name] to compile all the VBA code in your database and ensure it is error-free. If any errors are found in other VBA programs, locate and correct them, then recompile the project.
While unresolved errors will not prevent you from assigning or retrieving values from object properties, the VBA IntelliSense—which displays a list of an object’s properties and functions—will not work properly until the project compiles successfully.
Seeing the property list appear in IntelliSense is an invaluable aid during coding, especially while learning and experimenting with class objects.
Get / Set instead of the Get / Let Property Procedure.
In this version of the ClsVolume
class, we have omitted all the property procedures ClsArea
that were present in the previous version. Instead, we use Get and Set property procedures rather than the traditional Get/Let pair.
Take a look at the declaration: the private member p_Area
is declared as a ClsArea
class object. Normally, when an object is declared this way, we would create an instance of it in the Class_Initialize()
procedure.
However, in this approach, we have not instantiated it within the class. The plan is to create and populate the ClsArea
object in the user program, set its properties with appropriate values, and then pass it to the ClsVolume2
class. The class will then use these values during the final calculation phase.
Take note of the Set CArea()
procedure. Its ByRef parameter, AreaValue
, is declared as a ClsArea
object. When an ClsArea
instance is passed to this property procedure, the object variable AreaValue
receives it and assigns it to the private p_Area
property of the ClsVolume2
object.
This mechanism allows the ClsVolume2
class to use an externally created and populated ClsArea
object without having to instantiate it internally, maintaining flexibility and reusability.
The Get CArea() Property procedure returns the Object to the calling program.
In our earlier programs, we wrote property procedures for individual elements of an object, such as Length
, Width
, and Height
—to assign or retrieve values. In this version, the difference is that we are passing an entire object as a parameter to a Set property procedure.
To access a property of this passed object—for example, dblLength
—we use the syntax CArea.dblLength
. Here, the Get/Set property procedure name CArea
essentially becomes a child object of the main object when declared in the main program. Its individual properties can then be accessed directly using the object address, such as:
This approach allows the main object to interact with the entire child object and its properties as a single unit, simplifying property management and enhancing reusability.
A Test Program in Standard Module.
We will now create a small test program in a Standard Module to verify the functionality of our newly derived class object. ClsVolume2
.
-
Insert a new Standard Module into your project.
-
Copy and paste the following code into the module.
-
Save the module before running the program.
Public Sub SetNewVol2_1() 'Method 1/2 Dim Vol As New ClsVolume2 'ClsArea Object instantiated and passed to the 'Property Procedure Set CArea in ClsVolume2. Set Vol.CArea = New ClsArea 'declare and instantiate the object in one statement Stop Vol.CArea.strDesc = "Bed Room" Vol.CArea.dblLength = 90 Vol.CArea.dblWidth = 10 Vol.dblHeight = 10 'assign height to ClsVolume2 Stop Debug.Print "Description", "Length", "Width", "Area", "Height", "Volume" Debug.Print Vol.CArea.strDesc, Vol.CArea.dblLength, Vol.CArea.dblWidth, Vol.CArea.Area, Vol.dblHeight, Vol.Volume Set Vol.CArea = Nothing Set Vol = Nothing End Sub
Code Review Line by Line.
Let’s quickly review the VBA code above.
-
The first line instantiates the
ClsVolume2
class with the object nameVol
. -
After the comment lines, the
Set Vol.CArea
statement calls the property procedure and passes the newly instantiatedClsArea
object as its parameter.
I included a Stop
statement on the next line to pause the program so you can observe how the object is assigned to the CArea
property. We’ll explore how to inspect this in memory shortly.
-
The following four lines assign values to the
ClsArea
object properties (strDesc
,dblLength
,dblWidth
) and to thedblHeight
property of theClsVolume2
object. -
The next
Stop
statement pauses the program again, allowing you to inspect how these values are stored in memory. -
The subsequent line prints the headings in the Debug Window for clarity.
-
Finally, the last line prints the values of the object properties retrieved from memory, displaying them in the Debug Window.
Run the Code to the Next Stop Statement
Let’s run the code and inspect the memory to see what happens at each stage where the
Stop
statements are placed.-
Click anywhere inside the code and press F5 to run the program. The execution will pause at the first
Stop
statement. -
From the View menu, select Locals Window. This opens a window below the code editor that displays the
ClsArea
andClsVolume2
objects, along with their properties and member procedures, as they are stored in memory. -
Observe the structure of the objects and how the property values are held. A sample image of the Locals Window is shown below for reference.
The Locals Window View.
To give more space for the Locals Window, drag the sizing handles of other windows upward to reduce their height. Alternatively, you can close the Debug Window temporarily and press Ctrl+G to bring it back when needed.
The Locals Window provides a graphical view of all objects and their properties in memory:
-
The first item with a plus [+] symbol shows the name of the Standard Module from which the program is running.
-
The next plus [+] symbol represents the
Vol
object, which is the instantiatedClsVolume2
object in memory.
Click the plus [+] symbols to expand each item and display detailed information about the object’s properties and member procedures.
You will find the next level of Objects and Properties.
The [+]CArea indicates that this Object has the next level of Properties and their Values.
The dblHeight Get property Procedure comes directly under the Vol Object.
The [+]p_Area is the Private Property declared ClsArea Class in the ClsVolume2 Class.
The p_Height is also the Private Property declared in the ClsVolume2.
Click on the plus [+] symbols to expand the objects to show their Properties and Values.
Expanding the [+] CArea node displays the
ClsArea
object that was passed to theSet CArea()
property procedure.The expansion of [+]p_Area gives the view of the ClsArea Property declared as Private.
Note that the p_Area Private Property, of the ClsVolume2 Class Object, and all its elements are accessible only through the CArea Object Property Get/Set Procedures to the outside world.
The second column in the Locals Window displays the values assigned to the object’s properties. At this stage, no values have been assigned, so the fields are currently empty.
The Third Column shows the Data Type or Object Class Module Names.
Press F5 to run the program further, till it is paused at the next Stop statement, to assign some values to the Object Properties. The program will pause at the next Stop statement. Check the Locals Window for changes in Values.
Inside the CArea Object, the first two lines with values 90, 10, and the last strDesc Variable with value "Bedroom" are assigned through the Get Property Procedures, respectively. The p_Desc, p_Length, and p_width are values assigned through Set Property Procedures to the p_Area Property of the ClsVolume2 Class Object as well.
The p_Area Object of ClsArea Class declared as Private Property of ClsVolume2 is seen with its Get/Set Property Procedures and assigned values.
Check the Type Column of [-]CArea and [-]p_Area; both Objects are derived from the ClsArea Base Class.
Usage of ClsArea and ClsVolume2 Class Objects Differently.
Next week, we will explore another approach using the same two objects.
If you’d like to experiment on your own beforehand, here’s a clue to get you started:
Instantiate ClsVolume2 and ClsArea classes as two different Objects in the Standard Module Program.
Assign values to both Object Properties.
Assign the ClsArea instantiated Object to the CArea Object in the ClsVolume2 Class Object, before printing the Values to the Debug Window.
In this example, we can achieve the same result as in the previous example without having to repeat the Get/Let property procedures in the
ClsVolume
class module.The Links of All the Pages in this Topic.
- MS-Access Class Module and VBA
- MS-Access VBA Class Object Arrays
- MS-Access Base Class and Derived Objects
- VBA Base Class and Derived Objects-2
- Base Class and Derived Object Variants
- Ms-Access Recordset and Class Module
- Access Class Module and Wrapper Classes
- Wrapper Class Functionality Transformation
- Ms-Access and Collection Object Basics
- Ms-Access Class Module and Collection Object
- Table Records in Collection Object and Form
- Dictionary Object Basics
- Dictionary Object Basics-2
- Sorting Dictionary Object Keys and Items
- Display Records from Dictionary to Form
- Add Class Objects as Dictionary Items
- Add Class Objects as Dictionary Items
- Update Class Object Dictionary Item on Form
-
Thanks for your articles, it makes very interesting reading.
ReplyDeleteOne thing I would like to point out is this:
Public Property Set CArea(ByRef AreaValue As ClsArea)
Set p_Area = AreaValue
End Property
Normally if you omit the keyword, ByRef or ByVal, the default is ByRef.
However, I have noticed for Let and Set Properties, even if you add ByRef, it still behaves ByVal!
Set Property Procedure Assigns Object to an Object Variable. The Normal parameter usage is ByRef for Objects and Arrays. There are some places where I made some mistakes by Copy Pasting Code from earlier Articles and overlooked the corrections in some cases on these pages. Explicit ByVal parameter usage for Class Object didn't have any side effects in the Set Property Procedure. It appears that the ByVal clause is ignored by the System and the code worked correctly.
ReplyDeleteI will go through the Pages once again and will make correction.
Thanks for pointing out the mistakes.
For Objects, Arrays etc. need their location addresses passed to Functions, Sub-Routines or Property Procedures. You can pass the value of an array element to a function with ByVal, but not the entire Array. It needs to be passed by ByRef only, either by implicit or explicit reference.
DeleteIn the above case, where ByVal is used for a Class Object parameter, by mistake, the explicit ByVal usage is ignored for an Object and took it as ByRef by the System. Otherwise we will not get access to the Object Properties or Methods.