You will learn about the following in this chapter:
abstract functions and abstract classes
Polymorphism and why abstract functions and abstract classes are important for implementing polymorphic software
The dynamic binding mechanism, which is fundamental to polymorphism
The advantages of polymorphism and examples of how it empowers programmers
How type information is lost through up casting and how it can be regained through down casting by the use of the cast operator, the is operator and the as operator
The System.Object class, from which all classes are ultimately derived
Method hiding and method overriding
Versioning and how it is supported in C#
Multiple inheritance and why C# does not support it, but instead uses interfaces
How interfaces extend our ability to implement polymorphic code across the class hierarchies
How inheritance, interfaces and polymorphism allow us to implement generic programs
Not only does inheritance allow us to arrange our classes in neat taxonomical hierarchies and to reuse the code of these classes effectively, as shown in Chapter 16, "Inheritance Part I: Basic Concepts," it also allows us to implement a powerful concept called polymorphism. When polymorphism is applied on a class hierarchy, it involves one ancestor class and several of its descendant classes. However, sometimes we want to apply polymorphism to a group of classes that do not have a common ancestor. Interfaces presented later in this chapter help us to break free from the class hierarchy structure and apply polymorphism to groups of classes without common ancestors.
Before we look at polymorphism, we need to introduce abstract functions that play an important role for implementing polymorphism in class hierarchies.