Polymorphism is the ability for classes to provide different implementations of methods that are called by the same name. Polymorphism allows a method of a class to be called without regard to what specific implementation it provides. For example, you might have a class named Road which calls the Drive method of an additional class. This Car class may be SportsCar, or SmallCar, but both would provide the Drive method. Though the implementation of the Drive method would be different between the classes, the Road class would still be able to call it, and it would provide results that would be usable and interpretable by the Road class.
Polymorphism in components can be implemented in a variety of ways:
These three types of polymorphism are discussed in greater detail below.
A powerful technique in component programming is being able to implement multiple interfaces on an object. Each interface is composed of a small group of closely related methods, properties, and events. By implementing interfaces, your component can provide functionality to any other component requiring that interface, without regard to the particular functionality contained within. This allows successive versions of components to incorporate different capability without disturbing core functionality.
The features of your component most commonly used by other developers should naturally be members of the component class itself. However, components with a large number of members can be difficult to use. Consider factoring out some features of your component as separate interfaces that are implemented privately.
Another benefit of defining features in terms of interfaces is that you can add features to your component incrementally by defining and implementing additional interfaces. Advantages include:
Visual Basic and C# also 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. An over-emphasis on inheritance-driven polymorphism typically results in a massive shift of resources from coding to designing, which does nothing to shorten overall development time.
Given that the real test of software is whether it works for end users, tools for rapid prototyping and rapid application development (RAD) have gained wider acceptance than tools for object-oriented programming.
The foremost use of inheritance is to add functionality to an existing base class. Programmer productivity is much greater when you start with a framework of fully debugged base classes, and methods can be incrementally added to base classes without breaking versioning.
You may also wish to use inheritance when your application design includes several related classes that must share identical implementation for certain common functions. The overlapping functionality can be implemented in a base class, from which the classes used in the application can be derived. An abstract class combines features of both inheritance and implementation, and may be useful when elements of each are needed.
Abstract classes provide features of both inheritance and interface implementation. An abstract (MustInherit in Visual Basic) class is a class that cannot be instantiated, and must be implemented in an inheriting class. It may contain methods and properties that are already implemented, but it may also incorporate unimplemented procedures which must be implemented in the inheriting class. This allows you to provide an invariant level of functionality in some methods of your class, while leaving flexibility options open for other procedures. An additional benefit of abstract classes is that when new versions of your component are required, additional methods may be added to the base class as needed, whereas interfaces must remain invariant.
An abstract class is useful when you need a group of related components to incorporate a set of methods with identical functionality, but also require flexibility in the implementation of other methods. Abstract classes are also valuable when versioning issues are anticipated, because the base class remains flexible and easily modified. For details, see Recommendations for Abstract Classes vs. Interfaces.