Microsoft Office 2000/Visual Basic Programmer's Guide   

Implementing a Nonabstract Class

The abstract interfaces discussed in the previous section impose a discipline on a set of related objects. Each class contains the same properties and methods, at a minimum, and each class must provide the code that runs for a given property or method, which is desirable if the objects behave differently. In some cases, however, every object in the set may behave in exactly the same manner for a given property. In this case, you can implement an interface that contains the desired code in the Property procedure, and call that Property procedure from the corresponding property for each object.

For example, every class in the Library.xls sample implements the Name property for the object in an identical way. Each time you add a new type of object, you need to implement the Name property again. You can save yourself a little effort by moving the code for the Name property into the LibraryItem interface itself. Of course, each class must still implement the Name property. Instead of storing and retrieving the value itself, however, each class can delegate that task to the LibraryItem interface. In order to call code in the LibraryItem class, each class must contain a private variable of type LibraryItem, which can be initialized in the Class_Initialize event procedure:

Private p_colLibItem As LibraryItem

Private Sub Class_Initialize()
   Set p_colLibItem = New LibraryItem
End Sub

To delegate to the LibraryItem interface, the class must set and retrieve the Name property on this object of type LibraryItem:

Private Property Let LibraryItem_Name(ByVal RHS As String)
   ' Store name.
   p_colLibItem.Name = RHS
End Property

Private Property Get LibraryItem_Name() As String
   ' Return name.
   LibraryItem_Name = p_colLibItem
End Property

The only difference between implementing the Name property by delegating it to the LibraryItem interface and implementing it individually in each class module is that rather than storing a value in a module-level variable that's private to that class, you're storing a value in the Name property of a LibraryItem object, which in turn stores the value in its own private module-level variable.

Finally, note that when a class implements an interface, all the members that it implements are automatically denoted as private. This means that the implemented properties and methods in the Fiction, Nonfiction, Periodical, and Reference classes don't appear as part of the available interfaces for those objects. The implemented properties and methods appear on a variable of type LibraryItem only, which is fine if you're using variables of type LibraryItem to represent all of the other objects, as is done in the Library.xls sample.

If you want to define a public interface for each object, however, you can create a public property or method that calls the code that's in the private member. For example, if you wanted the Name property to be publicly available on an object, you could write a public Name property procedure that calls the private procedure supplied by the implemented interface, as shown in the following example:

Public Property Let Name(strName As String)
   LibraryItem_Name = strName
End Property

Public Property Get Name As String
   Name = LibraryItem_Name
End Property

You have a great deal of flexibility in how you define an interface. It can be fully abstract, nonabstract, or a combination of the two. Often a combination of the two types can be useful. For those members that share the same code, you can group that code in the interface. For those that don't, you can implement the code separately in each class.

For more examples of classes that implement abstract and nonabstract interfaces, see the Queries.xls sample file, available in the ODETools\V9\Samples\OPG\Samples\CH09 subfolder on the Office 2000 Developer CD-ROM.