Visual Basic Concepts
This topic continues the code example begun in "Creating and Implementing an Interface," adding properties to the Animal interface that was implemented in the Flea and Tyrannosaur classes. You may find it helpful to read that topic before beginning this one.
Suppose we give the Animal class an Age property, by adding a Public variable to the Declarations section:
Option Explicit
Public Age As Double
The Procedure drop downs in the code modules for the Tyrannosaur and Flea classes now contain property procedures for implementing the Age property, as shown in Figure 9.10.
Figure 9.10 Implementing property procedures
This illustrates a point made in "Adding Properties to a Class" earlier in this chapter. Using a public variable to implement a property is strictly a convenience for the programmer. Behind the scenes, Visual Basic implements the property as a pair of property procedures.
You must implement both procedures. The property procedures are easily implemented by storing the value in a private data member, as shown here:
Private mdblAge As Double
Private Property Get Animal_Age() As Double
Animal_Age = mdblAge
End Property
Private Property Let Animal_Age(ByVal RHS As Double)
mdblAge = RHS
End Property
The private data member is an implementation detail, so you have to add it yourself.
Note When Implements provides the template for a Property Set or Property Let, it has no way of determining the name of the last argument, so it substitutes the name RHS,
as shown in the code example above.
There's no data validation on a property implemented as a public data member, but that doesn't mean you can't add validation code to the Property Let for Animal_Age. For example, you might want to restrict the values to ages appropriate for a Tyrannosaur or a Flea, respectively.
In fact, this shows the independence of interface and implementation. As long as the interface matches the description in the type library, the implementation can be anything.
Before you go on to the next step, remove the implementation of the read-write Age property from both class modules.
Of course, allowing the age of an animal to be set arbitrarily is bad object design. The object should know its own age, and provide it to the user as a read-only property. Remove the public variable Age
from the Animal class, and add the template for a read-only age property, like this:
Public Property Get Age() As Double
End Property
Now the Procedure drop downs in the code windows for the Tyrannosaur and Flea classes contain only a single entry, Age [PropertyGet]. You might implement this for the Tyrannosaur as follows:
Private mdblBirth As Double
Private Property Get Animal_Age() As Double
Animal_Age = Now - mdblBirth
End Property
The code above returns the age of the Tyrannosaur in days. You could set mdblBirth
in the Initialize event of the Tyrannosaur class, as here:
Private Sub Class_Initialize()
mdblBirth = Now
End Sub
And of course you could return the property value in more commonly used units, such as dog years.
For More Information We've been tossing interfaces and objects around like they were the same thing, seemingly putting references to objects into one object variable, and references to interfaces into another. "Time Out for a Brief Discussion of Objects and Interfaces" clears matters up.