Free mag vol1 | Page 296

CHAPTER 6  UNDERSTANDING INHERITANCE AND POLYMORPHISM Understanding Abstract Classes Currently, the Employee base class has been designed to supply various data members for its descendents, as well as supply two virtual methods (GiveBonus() and DisplayStats()) that may be overridden by a given descendent. While this is all well and good, there is a rather odd byproduct of the current design; you can directly create instances of the Employee base class: // What exactly does this mean? Employee X = new Employee(); In this example, the only real purpose of the Employee base class is to define common members for all subclasses. In all likelihood, you did not intend anyone to create a direct instance of this class, reason being that the Employee type itself is too general of a concept. For example, if I were to walk up to you and say, “I’m an employee!” I would bet your very first question to me would be, “What kind of employee are you?” Are you a consultant, trainer, admin assistant, copyeditor, or White House aide? Given that many base classes tend to be rather nebulous entities, a far better design for this example is to prevent the ability to directly create a new Employee object in code. In C#, you can enforce this programmatically by using the abstract keyword in the class definition, thus creating an abstract base class: // Update the Employee class as abstract // to prevent direct instantiation. abstract partial class Employee { ... } With this, if you now attempt to create an instance of the Employee class, you are issued a compiletime error: // Error! Cannot create an instance of an abstract class! Employee X = new Employee(); At first glance, it might seem very strange to define a class that you cannot directly create. Recall however that base classes (abstract or not) are very useful, in that they contain all of the common data and functionality of derived types. Using this form of abstraction, we are able to model that the “idea” of an employee is completely valid; it is just not a concrete entity. Also understand that although we cannot directly create an abstract class, it is still assembled in memory when derived classes are created. Thus, it is perfectly fine (and common) for abstract classes to define any number of constructors that are called indirectly when derived classes are allocated. At this point, you have constructed a fairly interesting employee hierarchy. You will add a bit more functionality to this application later in this chapter when examining C# casting rules. Until then, Figure 6-6 illustrates the crux of your current design. 233