15.02.2015 Views

C# 4 and .NET 4

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

implementation inheritance ❘ 95<br />

You might be wondering why there is any special problem with derived classes. The reason is that when you<br />

create an instance of a derived class, there is actually more than one constructor at work. The constructor of<br />

the class you instantiate isn’t by itself sufficient to initialize the class — the constructors of the base classes<br />

must also be called. That’s why we’ve been talking about construction through the hierarchy.<br />

To see why base class constructors must be called, you’re going to develop an example based on a cell phone<br />

company called MortimerPhones. The example contains an abstract base class, GenericCustomer, which<br />

represents any customer. There is also a (non-abstract) class, Nevermore60Customer, which represents any<br />

customer on a particular rate called the Nevermore60 rate. All customers have a name, represented by a<br />

private field. Under the Nevermore60 rate, the first few minutes of the customer’s call time are charged at<br />

a higher rate, necessitating the need for the field highCostMinutesUsed, which details how many of these<br />

higher-cost minutes each customer has used up. The class definitions look like this:<br />

abstract class GenericCustomer<br />

{<br />

private string name;<br />

// lots of other methods etc.<br />

}<br />

class Nevermore60Customer: GenericCustomer<br />

{<br />

private uint highCostMinutesUsed;<br />

// other methods etc.<br />

}<br />

code snippet MortimerPhones.cs<br />

We won’t worry about what other methods might be implemented in these classes, because we are<br />

concentrating solely on the construction process here. And if you download the sample code for this chapter,<br />

you’ll find that the class definitions include only the constructors.<br />

Take a look at what happens when you use the new operator to instantiate a Nevermore60Customer:<br />

GenericCustomer customer = new Nevermore60Customer();<br />

Clearly, both of the member fields name <strong>and</strong> highCostMinutesUsed must be initialized when customer is<br />

instantiated. If you don’t supply constructors of your own, but rely simply on the default constructors, then<br />

you’d expect name to be initialized to the null reference, <strong>and</strong> highCostMinutesUsed initialized to zero.<br />

Let’s look in a bit more detail at how this actually happens.<br />

The highCostMinutesUsed field presents no problem: the default Nevermore60Customer constructor<br />

supplied by the compiler will initialize this field to zero.<br />

What about name Looking at the class definitions, it’s clear that the Nevermore60Customer constructor<br />

can’t initialize this value. This field is declared as private, which means that derived classes don’t have access<br />

to it. So, the default Nevermore60Customer constructor simply won’t know that this field exists. The only<br />

code items that have that knowledge are other members of GenericCustomer. This means that if name is<br />

going to be initialized, that’ll have to be done by some constructor in GenericCustomer. No matter how big<br />

your class hierarchy is, this same reasoning applies right down to the ultimate base class, System.Object.<br />

Now that you have an underst<strong>and</strong>ing of the issues involved, you can look at what actually happens whenever a<br />

derived class is instantiated. Assuming that default constructors are used throughout, the compiler first grabs<br />

the constructor of the class it is trying to instantiate, in this case Nevermore60Customer. The first thing that<br />

the default Nevermore60Customer constructor does is attempt to run the default constructor for the immediate<br />

base class, GenericCustomer. The GenericCustomer constructor attempts to run the constructor for its<br />

immediate base class, System.Object. System.Object doesn’t have any base classes, so its constructor just<br />

executes <strong>and</strong> returns control to the GenericCustomer constructor. That constructor now executes, initializing<br />

name to null, before returning control to the Nevermore60Customer constructor. That constructor in turn<br />

executes, initializing highCostMinutesUsed to zero, <strong>and</strong> exits. At this point, the Nevermore60Customer<br />

instance has been successfully constructed <strong>and</strong> initialized.<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!