Implementing a Nonabstract ClassThis content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.
The abstract interfaces discussed in Implementing an Abstract Interface 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 might 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 must 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. 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
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 are 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 do not 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 are 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 do not, you can implement the code separately in each class.
Why Build Your Own Objects? | Basic Class Concepts | Creating Property Procedures | Creating Events and Event Procedures | Extending Objects Through Interfaces | Designing Object Models | Creating Custom Objects for Web Pages