Adding Properties to a Class

See Also

The easiest way to define properties for a class is by adding public variables to the class module. For example, you could very easily create an Account class by declaring two public variables in a class module named Account:

Public Balance As Double
Public Name As String

This is pretty easy. It's just as easy to create private data for a class; simply declare a variable Private, and it will be accessible only from code within the class module:

Private mstrMothersMaidenName As String
Private mintWithdrawalsMonthToDate As Integer

Data Hiding

The ability to protect part of an object's data, while exposing the rest as properties, is called data hiding. This is one aspect of the object-oriented principle of encapsulation, as explained in "Classes: Putting User-Defined Types and Procedures Together."

Data hiding means that you can make changes in the implementation of a class — for example, increasing the Account class's private variable mintWithdrawalsMonthToDate from an Integer to a Long — without affecting existing code that uses the Account object.

Data hiding also allows you to define properties that are read-only. For example, you could use a Property Get procedure to return the value of the private variable containing the number of withdrawals in a month, while only incrementing the variable from within the Account object's code. Which brings us to property procedures.

Property Procedures

Data hiding wouldn't be much use if the only way you could create properties was by declaring public variables. How much good would it do you to give the Account class a Type property, if any code that had a reference to an Account object could blithely set the account type to any value at all?

Property procedures allow you to execute code when a property value is set or retrieved. For example, you might want to implement the Type property of the Account object as a pair of Property procedures:

Public Enum AccountTypes
   atSavings = 1
   atChecking
   atLineOfCredit
End Enum

' Private data storage for the Type property.
Private mbytType As AccountTypes

Public Property Get Type() As AccountTypes
   Type = mbytType
End Property

Public Property Let Type(ByVal NewType As AccountTypes)
   Select Case NewType
      Case atChecking, atSavings, atLineOfCredit
         ' No need to do anything if NewType is valid.
      Case Else
         Err.Raise Number:=vbObjectError + 32112, _
         Description:="Invalid account type"
   End Select
   If mbytType > NewType Then
      Err.Raise Number:=vbObjectError + 32113, _
      Description:="Cannot downgrade account type"
   Else
      mbytType = NewType
   End If
End Property

Now suppose you have a variable named acct that contains a reference to an Account object. When the code x = acct.Type is executed, the Property Get procedure is invoked to return the value stored in the class module's private data member mbytType.

When the code acct.Type = atChecking is executed, the Property Let is invoked. If the Account object is brand new, mbytType will be zero, and any valid account type can be assigned. If the current account type is atSavings, the account will be upgraded.

However, if the current account type is atLineOfCredit, the Property Let will raise an error, preventing the downgrade. Likewise, if the code acct.Type = 0 is executed, the Select statement in the Property Let will detect the invalid account type and raise an error.

In short, property procedures allow an object to protect and validate its own data.

For More Information   Are public variables good for anything, then? "Property Procedures vs. Public Variables" outlines the appropriate uses of both.

The capabilities of property procedures are explored further in "Putting Property Procedures to Work for You."