Visual Basic Concepts

Providing Polymorphism by Implementing Interfaces

One of the most striking features of the Component Object Model (COM) is the ability of an object to implement multiple interfaces. In addition to enabling polymorphism, multiple interfaces provide a mechanism for incremental or evolutionary development, without the need to recompile all the components in the system when changes occur.

By defining features in terms of interfaces, composed of small groups of closely-related functions, you can implement component features as needed, knowing that you can expand them later by implementing additional interfaces.

Maintaining compatibility is simplified, because new versions of a component can continue to provide existing interfaces, while adding new or enhanced interfaces. Succeeding versions of client applications can take advantage of these when it makes sense for them to do so.

Inheritance and Polymorphism

As explained in "Polymorphism" in "Programming with Objects," in the Visual Basic Programmer’s Guide, most object-oriented programming tools provide polymorphism through inheritance. This is a powerful mechanism for small-scale development tasks, but has generally proven to be problematic for large-scale systems.

In part, these difficulties arise as a result of necessary changes to classes deep in the inheritance tree. Recompilation is required in order to take advantage of such changes, and failure to recompile may lead to unpleasant surprises when the time finally arrives for a new version.

More seriously, an over-emphasis on inheritance-driven polymorphism typically results in a massive shift of resources from development tasks to up-front design tasks, doing nothing to address development backlogs or to shorten the time before the end user can discover — through hands-on experience — whether the system actually fulfills the intended purpose.

As a consequence, tools for rapid prototyping and Rapid Application Development (RAD) have gained wider acceptance than OOP tools.

Visual Basic and COM

Visual Basic follows the COM example, emphasizing multiple interfaces as a more flexible way to provide polymorphism. Software can evolve interface by interface, rather than having to be derived from all necessary antecedents during a lengthy design process.

Objects can begin small, with minimal functionality, and over time acquire additional features, as it becomes clear from actual use what those features should be. Legacy code is protected by continuing to support old interfaces while implementing new ones.

The Implements Feature

Visual Basic provides the Implements keyword as the means for incorporating a secondary interface. For example, if your project had a reference to a type library that described the IFinance interface, you could place the following code in a class module:

Implements IFinance

Because type libraries contain only interfaces, and no implementation, you would then add code for each of the properties and methods of the IFinance interface, as described in "Implementing and Using Standard Interfaces."

An Interface is a Contract

When you create an interface for use with Implements, you’re casting it in concrete for all time. This interface invariance is an important principle of component design, because it protects existing systems that have been written to an interface.

When an interface is clearly in need of enhancement, a new interface should be created. This interface might be called Interface2, to show its relationship to the existing interface.

While generating new interfaces too frequently can bulk up your components with unused interfaces, well-designed interfaces tend to be small and independent of each other, reducing the potential for performance problems.

Factoring Interfaces

The process of determining what properties and methods belong on an interface is called factoring.

In general, you should group a few closely-related functions on an interface. Too many functions make the interface unwieldy, while dividing the parts of a feature too finely results in extra overhead. For example, the following code calls methods on three different interfaces of the Velociraptor class:

Public Sub CretaceousToDoList(ByVal vcr1 As _
      Velociraptor, ByVal vcr2 As Velociraptor)
   Dim dnr As IDinosaur
   Dim prd As IPredator
   vcr1.Mate vcr2
   Set dnr = vcr1
   dnr.LayEggs
   Set prd = vcr1
   prd.KillSomethingAndEatIt
End Sub

In order to use methods on the IDinosaur and IPredator interfaces, you must assign the object to a variable of the correct interface type.

Where possible, interfaces designed to use flexible data structures will outlast interfaces based on fixed data types.

As noted above, it’s much harder to go wrong in designing interfaces than in creating large inheritance trees. If you start small, you can have parts of a system running relatively quickly. The ability to evolve the system by adding interfaces allows you to gain the advantages object-oriented programming was intended to provide.

Tools for Creating and Using Interfaces

The mechanics of interface creation are discussed in the following related topics, and in the documentation for the MkTypLib utility.

For More Information*   The Implements feature is discussed in detail in "Polymorphism" in "Programming with Objects," in the *Visual Basic Programmer’s Guide.