Chapter 4. Extensibility and Polymorphism

In the previous chapter, we saw how to define various types of classes and specify their members—fields, properties, and functions.

In this chapter, we’re going to start by looking at this again in more detail, and try to understand what underlying concepts we’re implementing when we use these different coding patterns. We’ll then introduce a couple of new concepts—inheritance and polymorphism—and the language features that help us implement them.

We’ve finished our ATC application, by the way. Having gotten a reputation for building robust mission-critical software on time and to spec, we’ve now been retained by the fire department to produce a training and simulation system for them. Example 4-1 shows what we have so far.

Example 4-1. Classes representing firefighters and fire trucks

class Firefighter
{
    public string Name { get; set; }

    public void ExtinguishFire()
    {
        Console.WriteLine("{0} is putting out the fire!", Name);
    }

    public void Drive(Firetruck truckToDrive, Point coordinates)
    {
        if (truckToDrive.Driver != this)
        {
            // We can't drive the truck if we're not the driver
            // But just silently failing is BADBAD
            // What we need is some kind of structured means
            // of telling the client about the failure
            // We'll get to that in Chapter 6
            return;
        }
        truckToDrive.Drive(coordinates);
    }
}

class Firetruck
{
    public Firefighter Driver { get; set; }
    public void Drive(Point coordinates)
    {
        if (Driver == null)
        {
            // We can't drive if there's no driver
            return;
        }

        Console.WriteLine("Driving to {0}", coordinates);
    }
}

We have a model of the Firetruck, which uses a Firefighter as its Driver. The truck can be instructed to drive somewhere (if it has a driver), and you can tell a Firefighter to drive the truck somewhere (if he is the designated driver).

You can think of this as modeling a relationship between a Firetruck and its Driver. That driver has to be a Firefighter. In object-oriented design, we call this relationship between classes an association.

Association Through Composition and Aggregation

An association is a kind of flexible, “arms length” relationship between two entities in the system. There are no particular constraints about the direction of the relationship: the firefighter can be associated with the truck, or the truck with the firefighter. Or both.

Any particular firefighter may have associations with other types, and we can always assign another driver to the fire truck; there’s no exclusivity. For instance, we can do something like this:

Firetruck truckOne = new Firetruck();
Firefighter joe = new Firefighter { Name  = "Joe" };
Firefighter frank = new Firefighter { Name = "Frank" };

truckOne.Driver = joe;
// Later...
truckOne.Driver = frank;

But what about the 30 foot retractable ladder that we happen to have on the fire truck; what kind of relationship exists between the ladder and the fire truck?

Here’s our ladder class:

class Ladder
{
    public double Length { get; set; }
}

This particular ladder is one of those powered, extensible rotating things that are built right into the truck. So let’s add a property to represent that (see Example 4-2).

Example 4-2. Fire truck with integral ladder

class Firetruck
{
    public Firefighter Driver { get; set; }

    readonly Ladder ladder = new Ladder { Length = 30.0 };
    public Ladder Ladder
    {
        get
        {
            return ladder;
        }
    }

    // ...
}

When we construct the Truck, it creates a 30-foot ladder for itself, with a read-only property to retrieve it.

We call this “made of” association between classes composition. The ladder is a built-in part of the fire truck, but the fire truck can never be a part of the ladder, and the truck itself is responsible for the life cycle of its own ladder.

What if we need to manage other equipment on the truck—a detachable coil of hose, for example:

class Hose
{
}

We could add a property to the Truck to get and set that (modeling a particular coil of hose being connected to the hose system on the truck):

public Hose Hose
{
    get;
    set;
}

This is another kind of composition relationship—one component of the Truck is a hose, and the truck certainly can’t be a part of the hose; but the containing object (the truck) no longer controls the creation and lifetime of its own piece of apparatus. Instead, we say that it aggregates the hose.

Of course, there are no hard-and-fast rules about these terms and the code you write; they are just concepts which we use when we are designing systems. The definitions we’ve used come from the Unified Modeling Language (UML) 2.0, and we’re just mapping them to C# language features.

Nonetheless, it is useful to have a common conceptual language for describing our systems and the common characteristics of the code we use to implement them. Equally, when you are looking at someone else’s code (remembering that “someone else” includes “past you”) it is helpful to be able to translate what was written into these standard modeling concepts.

So we have a software model of the Firetruck, which has a Ladder and a Hose and uses a Firefighter as its Driver. What about the fire chief?

The fire chief is just another firefighter. He can drive a truck. He can put out fires. But he can do other stuff too. For instance, he can delegate responsibility for putting out a fire to another firefighter.

The question we ask ourselves is this: is the FireChief a Firefighter with extra responsibilities? If the answer is yes, we are describing an is-a association (the FireChief is a Firefighter) which we can represent by an inheritance relationship.

Inheritance and Polymorphism

We’ll get into the nuances of the question in the preceding paragraph in a minute, but let’s assume for the time being that our answer to the question is yes (which, on face value, seems reasonable). Example 4-3 shows how we use inheritance in C#.

Example 4-3. Inheritance in C#

class FireChief : Firefighter
{
    public void TellFirefighterToExtinguishFire (Firefighter colleague)
    {
        colleague.ExtinguishFire();
    }
}

Notice that we use the colon in the class declaration to indicate that FireChief is a Firefighter. We then say that Firefighter is a base class of FireChief. Looking at the relationship from the other direction, we can also say that FireChief is a derived class of Firefighter.

We’ve added the extra function that allows the chief to tell a firefighter to extinguish a fire—which encapsulates that extra responsibility. What we haven’t had to do is to duplicate all the functionality of the firefighter; that comes along anyway.

We can now use the fire chief just as we would a firefighter, as shown in Example 4-4.

Example 4-4. Using base class functionality inherited by a derived class

Firetruck truckOne = new Firetruck();
FireChief bigChiefHarry = new FireChief { Name  = "Harry" };

truckOne.Driver = bigChiefHarry;
bigChiefHarry.Drive(truckOne, new Point(100,300));

Firefighter joe = new Firefighter { Name = "Joe" };

bigChiefHarry.TellFirefighterToExtinguishFire(joe);

Because bigChiefHarry is an object of type FireChief, and a FireChief is a Firefighter, we can assign him to be the driver of a truck and tell him to drive it somewhere. But because he is a FireChief, we can also ask him to tell Joe to put out the fire when he gets there.

Wherever we talk about a FireChief, we can treat the object as a Firefighter. This use of one type as though it were one of its bases is an example of polymorphism.

Equally, we could phrase that the other way around: we can successfully substitute an instance of a more-derived class where we expect a base class. This is known as the Liskov Substitution Principle (LSP) after computer scientist Barbara Liskov, who articulated the idea in a paper she delivered in 1987.

Warning

It is quite possible to derive one class from another in a way that means we can’t treat the derived class as its base type. The derived class could change the meaning or behavior of a function with the same signature as its base, or throw errors in situations where the base promised that everything would be fine—say, the base accepted parameters in the range 1–10, where the derived class accepts parameters in the range 2–5.

This violates the LSP, which is a very poor design practice, but it is very easy to slip into, especially if the classes evolve independently over time.

What happens if our client doesn’t know that Harry is a fire chief, though? What if we refer to the object via a reference typed to Firefighter instead?

FireChief bigChiefHarry = new FireChief { Name  = "Harry" };
// Another reference to Harry, but as a firefighter
Firefighter stillHarry = bigChiefHarry;

Firefighter joe = new Firefighter { Name = "Joe" };

stillHarry.TellFirefighterToExtinguishFire(joe);

You know that stillHarry is referencing an object that is a FireChief, with that extra method on it. But the compiler produces a long, semicomprehensible error full of useful suggestions if you try to compile and execute this code:

'Firefighter' does not contain a definition for
 'TellFirefighterToExtinguishFire' and no extension method
 'TellFirefighterToExtinguishFire' accepting a first argument of type
 'Firefighter' could be found (are you missing a using directive or an
 assembly reference?)

The compiler is being rather tactful. It is assuming that you must’ve forgotten to include some external reference that’s got a suitable extension method definition to fix your problem. (We’ll be looking at that technique in a later chapter, by the way.)

Unfortunately, the real reason for our bug is hidden in the error’s opening salvo: we’re trying to talk to a FireChief method through a variable that is strongly typed to be a Firefighter, and you can’t call on any members of the derived class through a reference typed to a base.

So, if we can’t use a derived member from a reference to a base type, is there any way we can refine these classes so that Harry never puts out a fire, but always passes responsibility to his Number One when he’s asked to do so, regardless of whether we happen to know that he’s a FireChief? After all, he knows that he’s the boss!

To get started, we’ll have to make a few changes to the model to accommodate this idea of the chief’s Number One. In other words, we need to create an association between the FireChief and his NumberOne. Remember that we typically implement this as a read/write property, which we can add to the FireChief:

public Firefighter NumberOne
{
    get;
    set;
}

And let’s change the main function so that it does what we want (see Example 4-5).

Example 4-5. Using base class methods to keep the compiler happy

// A reference to Joe, Harry's number one
Firefighter joe = new Firefighter { Name = "Joe" };

// Firefighter harry is really a firechief, with joe as his NumberOne
Firefighter harry = new FireChief { Name  = "Harry", NumberOne = joe };

// Harry is just a firefighter, so he can extinguish fires
// but we want him to get joe to do the work
harry.ExtinguishFire();

But if we compile that, here’s the output we get:

Harry is putting out the fire!

That’s not what we want at all. What we want is a different implementation for that ExtinguishFire method if we’re actually a FireChief, rather than an ordinary Firefighter.

Replacing Methods in Derived Classes

So the implementation for the ExtinguishFire method that we want on the FireChief looks like this:

public void ExtinguishFire()
{
    // Get our number one to put out the fire instead
    TellFirefighterToExtinguishFire(NumberOne);
}

What happens if we just add that function to our FireChief and compile and run?

Well, it compiles, but when we run it, it still says:

Harry is putting out the fire!

It seems to have completely ignored our new function!

Let’s go back and have a look at that compiler output again. You’ll see that although it built and ran, there’s a warning (you may have to rebuild to get it to appear again; Choose Rebuild Solution from the Build menu):

'FireChief.ExtinguishFire()' hides inherited member
 'Firefighter.ExtinguishFire()'. Use the new keyword if hiding was intended.

Note

It is a good idea to leave all your compiler warnings on and work until you are both error and warning free. That way, when something crops up unexpectedly like this, you can spot it easily, rather than burying it in a pile of stuff you’re habitually ignoring.

It is telling us that, rather than replacing the implementation on the base class, our method (with matching signature) is hiding it; and that if this is what we really meant to do, we should add the keyword new to the method.

Hiding Base Members with new

OK, let’s do that:

public new void ExtinguishFire()
{
    // Get our number one to put out the fire instead
    TellFirefighterToExtinguishFire(NumberOne);
}

We typically add the new modifier between the accessibility modifier and the return value.

Compile and run again. You’ll notice that we’ve gotten rid of the warning, but the output hasn’t changed:

Harry is putting out the fire!

What’s going on?

This method-hiding approach is actually letting a single object provide different implementations for the ExtinguishFire method. The implementation we get is based on the type of the variable we use, rather than the type of object to which the variable refers. You can see that happening if we use the code in Example 4-6 in our client.

Example 4-6. Different reference type, different method

// A reference to Joe, Harry's number one
Firefighter joe = new Firefighter { Name = "Joe" };

// Firefighter harry is really a firechief, with joe as his NumberOne
FireChief harry = new FireChief { Name  = "Harry", NumberOne = joe };
Firefighter harryAsAFirefighter = harry;

// Harry is just a firefighter, so he can extinguish fires
// but as a firechief he gets joe to do the work
harry.ExtinguishFire();
// While as a firefighter he does it himself
harryAsAFirefighter.ExtinguishFire();

The output we get now looks like this:

Joe is putting out the fire!
Harry is putting out the fire!

When we talk to our Harry object through a FireChief reference, he gets Joe to put out the fire. If we talk to the object through a Firefighter reference, he does it himself. Same object, but two completely different implementations.

Why might we want to do that?

Let’s say we had multiple fire chiefs on a job, but it is our policy that a chief acting as another chief’s Number One is not allowed to delegate the job again. Our code models exactly this behavior, as shown in Example 4-7.

Note

Of course, whether that’s desirable behavior is another matter entirely—we’ve ended up with such radically different approaches to putting out a fire that it might be better to separate them back out into functions with different names.

When you go through a refactoring process such as this, it is a good idea to check that you’re still happy with the semantic implications of your code. Ideally, you want to end up with a neat design, but a superficially neat design that makes no sense is not helpful.

Example 4-7. Making twisted use of method hiding

// A reference to Joe, Harry's number one
Firefighter joe = new Firefighter { Name = "Joe" };

// FireChief harry has joe as his NumberOne
FireChief harry = new FireChief { Name  = "Harry", NumberOne = joe };
FireChief tom = new FireChief { Name = "Tom", NumberOne = harry };

// Harry is just a firefighter, so he can extinguish fires
// but as a firechief he gets joe to do the work
harry.ExtinguishFire();

// But if Tom is asked to extinguish a fire, he asks Harry to do it
// Our policy dictates that Harry has to do it himself, not delegate to
// Joe this time.
tom.ExtinguishFire();

Harry delegates to Joe when he is asked to do it himself, because we are calling through a reference to a FireChief.

Tom is also a FireChief, and we are calling through a reference to him as a FireChief, so he delegates to Harry; but when Harry is asked to do it in his role as a Firefighter (remember, the NumberOne property is a reference to a Firefighter), he does it himself, because we are now calling the method through that reference typed to Firefighter.

So our output looks like this:

Joe is putting out the fire!
Harry is putting out the fire!

That’s all very well, but we don’t actually want that restriction—the fire chief should be allowed to pass the work off to his subordinate as often as he likes, regardless of who he asked to do it.

Warning

There’s one big caveat regarding everything we’ve just shown about method hiding: I can’t think of the last time I used this feature in a real application, but I see the warning from time to time and it usually alerts me to a mistake in my code.

We’ve wanted to illustrate how method hiding works, but we discourage you from using it. The main reason to avoid method hiding with new is that it tends to surprise your clients, and that, as we’ve established, is not a good thing. (Would you really expect behavior to change because the type of the variable, not the underlying object, changes?)

While method hiding is absolutely necessary for some corner cases, we usually treat this warning as an error, and think very carefully about what we’re doing if it comes up. 9 times out of 10, we’ve got an inadvertent clash of names.

Replacing Methods with virtual and override

What we actually want to do is to change the implementation based on the type of the object itself, not the variable we’re using to get at it. To do that we need to replace or override the default implementation in our base class with the one in our derived class. A quick glance at the C# spec shows us that there is a keyword to let us do just that: override.

Let’s switch to the override modifier on the FireChief implementation of the ExtinguishFire() method:

public override void ExtinguishFire()
{
    // Get our number one to put out the fire instead
    TellFirefighterToExtinguishFire(NumberOne);
}

Notice that we removed the new modifier and replaced it with override instead. But if you compile, you’ll see that we’re not quite done (i.e., we get a compiler error):

'FireChief.ExtinguishFire()': cannot override inherited member
'Firefighter.ExtinguishFire()' because it is not marked virtual, abstract,
or override

We’re not allowed to override the method with our own implementation because our base class has to say we’re allowed to do so. Fortunately, we wrote the base class, so we can do that (as the compiler error suggests) by marking the method in the base with the virtual modifier:

class Firefighter
{
    public virtual void ExtinguishFire()
    {
        Console.WriteLine("{0} is putting out the fire!", Name);
    }

    // ...
}

Why do we have this base-classes-opt-in system? Why is everything not virtual by default (like, say, Java)? Arguments continue on this very issue, but the designers of C# chose to go with the nonvirtual-by-default option. There are a couple of reasons for this: one has to do with implicit contracts, and another is related to versioning.

Note

There is also (potentially) a small performance overhead for virtual function dispatch, but this is negligible in most real-world scenarios. As always, test before optimizing for this!

We already saw how our public API is effectively a contract with our clients. With virtual functions, though, we are defining not only a contract for the caller, as usual, but also a contract for anyone who might choose to override that method. That requires more documentation, and a greater degree of control over how you implement the method.

Note

By declaring a method as virtual, the base class gives derived classes permission to replace whole pieces of its own innards. That’s a very powerful but very dangerous technique, rather like organ transplant surgery on an animal you’ve never seen before. Even a trained surgeon might balk at replacing the kidneys of a dromedary armed with nothing more than developer-quality documentation about the process.

For example, some method in your base class calls its MethodA, then its MethodB, to do some work. You then (perhaps unknowingly) rely on that ordering when you provide overrides for MethodA and MethodB. If a future version of the base class changes that ordering, you will break.

Let’s go back to our example to look at that in more detail, because it is really important.

First, let’s change the implementation of Firefighter.ExtinguishFire so that it makes use of a couple of helper methods: TurnOnHose and TrainHoseOnFire (see Example 4-8).

Example 4-8. Virtual methods and method ordering

class Firefighter
{
    // This calls TrainHoseOnFire and TurnOnHose as part of the
    // process for extinguishing the fire
    public virtual void ExtinguishFire()
    {
        Console.WriteLine("{0} is putting out the fire!", Name);
         TrainHoseOnFire();
         TurnOnHose();
    }

    private void TurnOnHose()
    {
        Console.WriteLine("The fire is going out.");
    }

    private void TrainHoseOnFire()
    {
        Console.WriteLine("Training the hose on the fire.");
    }

    // ...
}

Let’s also simplify our Main function so that we can see what is going on, as shown in Example 4-9.

Example 4-9. Calling a virtual method

static void Main(string[] args)
{
    // A reference to Joe, Harry's number one
    Firefighter joe = new Firefighter { Name = "Joe" };
    joe.ExtinguishFire();

    Console.ReadKey();
}

If we compile and run, we’ll see the following output:

Joe is putting out the fire!
Training the hose on the fire.
The fire is going out.

All is well so far, but what happens if we add a trainee firefighter into the mix? The trainee is extremely fastidious and follows his instructor’s guidelines to the letter. We’re going to make a class for him and override the TurnOnHose and TrainHoseOnFire methods so that the work is done in the trainee’s own particular idiom.

Hang on a moment, though! Our helper methods are private members. We can’t get at them, except from other members of our Firefighter class itself.

Before we can do anything, we need to make them accessible to derived classes.

Inheritance and Protection

In the preceding chapter, we mentioned that there were two additional accessibility modifiers that we would deal with later: protected and protected internal. Well, this is where they come into their own. They make members accessible to derived classes.

If you want a member to be available either to derived classes or to other classes in your own assembly, you mark that member protected internal. It will be visible to other classes in the library, or to clients that derive classes from your base, but inaccessible to other clients who just reference your assembly.

If, on the other hand, you want your class to make certain methods available only to derived classes, you just mark those methods protected. In terms of code out there in the wild, this is the most common usage, but it is not necessarily the best one!

Note

Both protected internal and internal are much underused access modifiers. They are a very convenient way of hiding away library implementation details from your consumers, and reducing the amount of documentation and surface-area testing you need.

I suspect that they are unpopular (as with most “hidden by default” or “secure by default” schemes) because they can sometimes get in your way. There are a fair number of implementation details of classes in the .NET Framework that are internal (or private) that people would very much like to access, for example.

A common reason for taking something useful and applying the internal modifier is that it was not possible to fully document (or understand the full implications of) the “hook” this would provide into the framework. And rather than open up potential security or reliability problems, they are marked internal until a later date: perhaps much, much later, tending toward never. Although there is an intention to revisit these things, real-world pressures mean that they often remain unchanged.

This is another example of the “lock down by default” strategy which helps improve software quality.

That doesn’t make it any less irritating when you can’t get at the inner workings, though!

So we’ll mark those methods in the base class virtual and protected, as shown in Example 4-10.

Example 4-10. Opening methods up to derived classes

    protected virtual void TurnOnHose()
    {
        Console.WriteLine("The fire is going out.");
    }

    protected virtual void TrainHoseOnFire()
    {
        Console.WriteLine("Training the hose on the fire.");
    }

We can now create our TraineeFirefighter class (see Example 4-11).

Example 4-11. Overriding the newly accessible methods

class TraineeFirefighter : Firefighter
{
    private bool hoseTrainedOnFire;
    protected override void TurnOnHose()
    {
        if (hoseTrainedOnFire)
        {
            Console.WriteLine("The fire is going out.");
        }
        else
        {
            Console.WriteLine("There's water going everywhere!");
        }
    }

    protected override void TrainHoseOnFire()
    {
        hoseTrainedOnFire = true;
        Console.WriteLine("Training the hose on the fire.");
    }
}

As you can see, the trainee is derived from Firefighter. We added an extra Boolean field to keep track of whether the trainee has actually trained the hose on the fire, and then provided our own implementations of TrainHoseOnFire and TurnOnHose that make use of that extra field. This is intended to model the detailed but slightly peculiar and occasionally erratic way in which the trainee follows the instructions for these operations in his copy of How to Be a Firefighter, rather than allowing common sense to prevail.

We also need a quick update to our main function to use our trainee. Let’s add the following code at the end:

// A reference to Bill, the trainee
Firefighter bill = new TraineeFirefighter { Name = "Bill" };
bill.ExtinguishFire();

If we compile and run, we see the following output:

Joe is putting out the fire!
Training the hose on the fire.
The fire is going out.

Bill is putting out the fire!
Training the hose on the fire.
The fire is going out.

Well done, Bill; all that training came in handy, exactly as we’d expect.

Although it works, you’ll notice that we’ve duplicated some code from our base class into our derived class—the bit that actually does the work in each of those methods. It would be better if we could just call on our base class implementation to do the job for us. As you’d expect, C# has this in hand, with the base keyword.

Calling Base Class Methods

If we ever want to call on the implementation of a member in our base class (bypassing any of our own overrides), we can do so through the special base name:

base.CallOnTheBase();

Using that, we can reimplement our TraineeFirefighter and remove that duplicate code, as shown in Example 4-12.

Example 4-12. Avoiding duplication by calling the base class

class TraineeFirefighter : Firefighter
{
    private bool hoseTrainedOnFire;
    protected override void TurnOnHose()
    {
        if (hoseTrainedOnFire)
        {
            // Call on the base implementation
            base.TurnOnHose();
        }
        else
        {
            Console.WriteLine("There's water going everywhere!");
        }
    }

    protected override void TrainHoseOnFire()
    {
        hoseTrainedOnFire = true;
        base.TrainHoseOnFire();
    }
}

So, what happens if in a later version we change the implementation of the ExtinguishFire method on the base class? Maybe we found an optimization that means it is faster to implement it like this:

public virtual void ExtinguishFire()
{
    Console.WriteLine("{0} is putting out the fire!", Name);
    // We've swapped these around
    TurnOnHose();
    TrainHoseOnFire();
}

Let’s imagine that this Firefighter class is being implemented by one of our colleagues. She tested the new implementation against her Firefighter unit test suite, exactly as required, and everything passed just fine—fires were extinguished. Then she handed it over to us to use (with our new TraineeFirefighter class that we’re working on).

If we compile and run, we get the following output:

Joe is putting out the fire!
Training the hose on the fire.
The fire is going out.

Bill is putting out the fire!
There's water going everywhere!
Training the hose on the fire.

So the Firefighter code works fine, just as our colleague promised; but our TraineeFirefighter has made a bit of a mess. This is a shame, as he has not done anything different—we didn’t change a single line of our TraineeFirefighter code that was working just a moment earlier.

The problem is that, while our documentation for ExtinguishFire told us that it would call both of those virtual methods it didn’t promise to do so in any particular order. And there was no documentation at all on our protected virtual methods to tell us how we should override them, or whether there were any particular constraints or invariants we should maintain.

Warning

This is a very common combination of problems when designing an inheritance hierarchy—poor documentation on the base class, and insufficiently defensive implementations in a derived class. Creating a class hierarchy is not an easy thing to do. And this is when we’re only making selected methods virtual—imagine the chaos if all methods were virtual by default!

In the next chapter, we’re going to look at some alternative ways to vary behavior that are more easily documented and potentially more robust than deriving from a base class.

That’s not to say that you shouldn’t make use of such a powerful concept as polymorphism; it is just that you should take care when you do so.

Let’s just recap the implications of all that, as it is a bit complicated.

Back in Chapter 3, when we designed our first class, we talked about its public contract, and how that encapsulated the implementation details which allowed us to use it as though it was a black box.

With the addition of public and protected virtual members, we’re opening that black box and creating a second contract: for people who derive their own classes, which, as we just saw, is a whole lot more complex.

The designers of C# decided that should be an opt-in complexity: unless we specify that a member is virtual we don’t have to worry about it. Along the same lines, they’ve also provided a way to ensure that we don’t have to worry about anyone deriving from us at all.

Thus Far and No Farther: sealed

Having got through all of that, you’re probably rightly concerned that, simple though it is in theory, the practical implications of inheritance are actually rather complex and require a lot of documentation, testing, and imagining how people might use and abuse your virtual methods. And we have to do that for every class down the hierarchy.

When we designed our FireChief, we happily provided an override for the ExtinguishFire method, without giving a thought for the fact that someone else might override that method in his own derived class. In fact, we didn’t even consider the possibility that anyone might derive from FireChief at all. No documentation, nothing.

Now there are several members on our own base class that could be overridden by a class that derives from FireChief. Does that have any implications for our own documentation or testing? Can we even tell? And how could we have guessed that was going to happen when we built our FireChief class, since there was only one virtual member on the base at that time? This looks like it has the potential to become a rich future source of bugs and security holes.

Fortunately, we can eliminate this problem at a stroke by saying that we didn’t design our FireChief to be derived from, and stopping anyone from doing so. We do that by marking the FireChief class sealed. Let’s see how that looks:

sealed class FireChief : Firefighter
{
    // ...
}

We apply the sealed modifier before the class keyword and after any accessibility modifiers if they are present.

So, what happens if we try to derive a new class from FireChief now?

class MasterChief : FireChief
{
}

Compile it, and you’ll see the following error:

'MasterChief': cannot derive from sealed type 'FireChief'

That’s put a stop to that. Let’s delete our MasterChief so that everything builds again.

Warning

Not only can sealing classes be very useful (and defensive), but if you decide later that you want to unseal the class and allow people to derive their own types, it doesn’t (normally) break binary compatibility for the type. Sealing a previously unsealed class, however, does break compatibility.

We now have three different types of firefighter. Let’s remind ourselves how they are related (see Figure 4-1).

Three types of firefighter

Figure 4-1. Three types of firefighter

Those three types of firefighter basically differ in the strategy that they use for putting out fires. There’s a base class that provides a default implementation, and a couple of classes that override the virtual methods to do things differently.

Let’s say we wanted to support lots of different types of firefighter, all of whom were expected to have a different approach to fighting fire, from the trainee, to the chief, to Gulliver (who has his own idiosyncratic way of putting out a fire in Lilliput).

We still want the handy Name property and the Drive method, and we still want anyone to be able to call an ExtinguishFire method.

Noticing that our FireChief, for example, doesn’t make use of the base implementation at all; we don’t want to provide a standard for that method. We’ll just let all implementers decide for themselves how it is going to work.

We’re shooting for something that looks like Figure 4-2.

Abstract base classes

Figure 4-2. Abstract base classes

Requiring Overrides with abstract

An abstract base class is intended to provide the “scaffolding” for a hierarchy of related classes, but it is not intended to be instantiated itself, because it isn’t “finished.” It requires that classes derived from it add in some missing bits.

Let’s turn our current firefighter into an abstract base for the others to use, and see how that works.

First, we can add the abstract modifier to the class itself, and see what happens:

abstract class Firefighter
{
    // ...
}

As usual, we add the modifier before the class keyword (and after any accessibility modifiers, if present).

If we build, we now get a compiler error:

Cannot create an instance of the abstract class or interface 'Firefighter'

That’s because we’re trying to create an instance of the Firefighter in our main function:

Firefighter joe = new Firefighter { Name = "Joe" };

This is no longer allowed, because the Firefighter class is now abstract.

OK, we’ll comment that out temporarily while we carry on refactoring. We want it to continue to build as we go so that we can see if we’ve introduced any other errors:

//Firefighter joe = new Firefighter { Name = "Joe" };
//joe.ExtinguishFire;

Build and run, and we get the output we expect—Bill is still spraying the water around:

Bill is putting out the fire!
There's water going everywhere!
Training the hose on the fire.

One other thing: if we’re creating an abstract base class, we usually name it something such as FooBase to distinguish it from a regular class. This is by no means a hard-and-fast rule, but it is pretty common. So let’s rename Firefighter to FirefighterBase, and make sure we change it where it is referenced elsewhere—on the Firetruck, FireChief, and TraineeFirefighter classes.

The easiest way to do that is to use the automatic rename refactoring in the IDE. Just type over the old name in the declaration, click on the Smart Tag that appears, and choose Rename Firefighter to FirefighterBase from the menu. You could do it by hand if you wanted, though.

The whole purpose of this was to get rid of the default implementation we have for putting out fires, so let’s turn Firefighterbase.ExtinguishFire into an abstract method.

Just like the modifier for the class, we use the abstract keyword, but this time we also remove the method body and add a semicolon at the end of the declaration:

abstract class FirefighterBase
{
    public abstract void ExtinguishFire();
}

If you try building again now, you can see that we have a new compiler error:

'TraineeFirefighter' does not implement inherited abstract member
'FirefighterBase.ExtinguishFire()'

Remember, we are required to override an abstract method; our class isn’t finished until we do so (unlike a virtual method, where we are invited to override it, but it will fall back on the base if we don’t). While our FireChief does override the method, our TraineeFirefighter doesn’t. So we need to add a suitable implementation:

 class TraineeFirefighter : FirefighterBase
 {
    // Override the abstract method
    public override void ExtinguishFire()
    {
        // What are we going to put here?
    }
    // ...
}

But what are we going to put into that ExtinguishFire override? Before, we depended on our base class for the implementation, but our base is now abstract, so we don’t have one available anymore!

That’s because we’ve forgotten about our regular Firefighter. Let’s add a class for him back into the hierarchy:

class Firefighter : FirefighterBase
{
    public override void ExtinguishFire()
    {
        Console.WriteLine("{0} is putting out the fire!", Name);
        TurnOnHose();
        TrainHoseOnFire();
    }
}

Notice we’ve given him the “standard firefighter” implementation for ExtinguishFire.

If we take one more look at the base class, we can see that we still have those two virtual implementation helpers. While everything builds correctly at the moment, they don’t really belong there; they are really a part of the Firefighter implementation, so let’s move them in there. We end up with the code in Example 4-13.

Example 4-13. Refactored base classes

abstract class FirefighterBase
{
    public abstract void ExtinguishFire();

    public string Name { get; set; }

    public void Drive(Firetruck truckToDrive, Point coordinates)
    {
        if (truckToDrive.Driver != this)
        {
            // We can't drive the truck if we're not the driver
            return;
        }
        truckToDrive.Drive(coordinates);
    }
}

class Firefighter : FirefighterBase
{
    public override void ExtinguishFire()
    {
        Console.WriteLine("{0} is putting out the fire!", Name);
        TrainHoseOnFire();
        TurnOnHose();
    }

    protected virtual void TurnOnHose()
    {
        Console.WriteLine("The fire is going out.");
    }

    protected virtual void TrainHoseOnFire()
    {
        Console.WriteLine("Training the hose on the fire.");
    }
}

But we’re still not quite done! If you build this you’ll see another compiler error:

'TraineeFirefighter.TurnOnHose()': no suitable method found to override
'TraineeFirefighter.TrainHoseOnFire()': no suitable method found to override

Our trainee firefighter really is a kind of firefighter, and depends on those two virtual functions we just moved. The error message is telling us that we can’t override a method that isn’t actually present in the base.

We need to change its base class from FirefighterBase to Firefighter. This has the advantage that we can also get rid of its duplicate override of the ExtingushFire method (see Example 4-14).

Example 4-14. Using the newly refactored base classes

class TraineeFirefighter : Firefighter
{
    protected override void TurnOnHose()
    {
        if (hoseTrainedOnFire)
        {
            Console.WriteLine("The fire is going out.");
        }
        else
        {
            Console.WriteLine("There's water going everywhere!");
        }
    }

    private bool hoseTrainedOnFire;
    protected override void TrainHoseOnFire()
    {
        hoseTrainedOnFire = true;
        Console.WriteLine("Training the hose on the fire.");
    }
}

We also need to uncomment our two lines about Joe in the Main function—everything should work again:

Firefighter joe = new Firefighter { Name = "Joe" };
joe.ExtinguishFire();

We can build and run to check that. We get the expected output:

Joe is putting out the fire!
Training the hose on the fire.
The fire is going out.

Bill is putting out the fire!
There's water going everywhere!
Training the hose on the fire.

Let’s remind ourselves of the current class hierarchy (see Figure 4-2). Our FireChief is no longer an “ordinary” Firefighter, with an override for putting out fires, but he does take advantage of our common scaffolding for “firefighters in general” that we modeled as an abstract base class called FirefighterBase. Our Firefighter also takes advantage of that same scaffolding, but our TraineeFirefighter really is a Firefighter—just with its own idiosyncratic way of doing some of the internal methods that Firefighter uses to get the job done.

Back to the requirements for our fire department application: let’s say we want to keep track of who is actually in the fire station at any particular time, just in case there is a fire on the premises and we can take a roll call (health and safety is very important, especially in a fire station).

There are two types of folks in the fire station: the firefighters and the administrators. Example 4-15 shows our new Administrator class.

Example 4-15. A class representing administrative staff

class Administrator
{
    public string Title { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Name
    {
        get
        {
            StringBuilder name = new StringBuilder();
            AppendWithSpace(name, Title);
            AppendWithSpace(name, Forename);
            AppendWithSpace(name, Surname);
            return name.ToString();
        }
    }

    void AppendWithSpace(StringBuilder builder, string stringToAppend)
    {
        // Don't do anything if the string is empty
        if (string.IsNullOrEmpty(stringToAppend))
        {
            return;
        }

        // Add a space if we've got any text already
        if (builder.Length > 0)
        {
            builder.Append(" ");
        }
        builder.Append(stringToAppend);
    }
}

If you look at our Firefighter class, it had a single string property for a Name. With the Administrator, you can independently get and set the Title, Forename, and Surname. We then provided a special read-only property that returns a single formatted string for the whole Name. It uses a framework class called StringBuilder to assemble the name from the individual components as efficiently as possible.

AppendWithSpace is a utility function that does the actual work of concatenating the substrings. It works out whether it needs to append anything at all using a static method on string that checks whether it is null or empty, called IsNullOrEmpty; finally, it adds an extra space to separate the individual words.

To do the roll call we want to write some code such as that in Example 4-16.

Example 4-16. Using the Administrator class

static void Main(string[] args)
{
    FireStation station = new FireStation();

    // A reference to Joe, Harry's number one
    Firefighter joe = new Firefighter { Name = "Joe" };

    // A reference to Bill, the trainee
    FirefighterBase bill = new TraineeFirefighter { Name = "Bill" };

    // Harry is back
    FireChief bigChiefHarry = new FireChief { Name = "Harry"};

    // And here's our administrator - Arthur
    Administrator arthur = new Administrator
    {
        Title = "Mr",
        Forename = "Arthur",
        Surname = "Askey"
    };

    station.ClockIn(joe);
    station.ClockIn(bill);
    station.ClockIn(bigChiefHarry);
    station.ClockIn(arthur);

    station.RollCall();

    Console.ReadKey();
}

Note

When you are designing a class framework it can often be a good idea to write some example client code. You can then ensure that your design is a good abstract model while supporting clean, simple code at point-of-use.

Clearly, we’re going to need a FireStation class that is going to let our administrators and firefighters ClockIn (registering their presence in the station), and where we can do a RollCall (displaying their names). But what type is that ClockIn function going to take, given that we haven’t specified any common base class that they share?

All Types Are Derived from Object

.NET comes to our rescue again. It turns out that every type in the system is derived from Object. Every one—value types (struct) and reference types (class) alike, even the built-in types such as Int32.

It is easy to see how that would work for a class declaration in C#. If you don’t specify a particular base class, you get Object by default.

But what about a struct, or enum, or the built-in types; what happens if we try to talk to them through their Object “base class”?

Boxing and Unboxing Value Types

Let’s give it a try. This code snippet will compile and work quite happily:

// Int variable
int myIntVariable = 1;
object myObject = myIntVariable;

What happens under the covers is that the runtime allocates a new object and puts a copy of the value inside it. This is called boxing, and, as you might expect given that it involves allocating objects and copying values, it is relatively expensive when compared to a straightforward assignment.

You can also convert back the other way:

// Int variable
int myIntVariable = 1;
object myObject = myIntVariable;
int anotherIntVariable = (int)myObject;

Notice how we use the type name in parentheses to perform the conversion back to an int. In general, this sort of conversion from one type to another is known as a “cast,” and will work for classes too (although we’ll see a more explicit way of doing that later in this chapter).

The runtime looks at that box object for us and checks that it contains a value of the correct type. If so, it will copy the value back out of the box and into the new variable.

Note

What if it isn’t of the correct type? The runtime will throw an InvalidCastException. You can find out more about exceptions in Chapter 6.

That process is known as unboxing, and is also quite expensive (although not as expensive as boxing, as it doesn’t need to allocate the object).

Although these performance costs are individually fairly small, if you are processing large numbers of value types in a way that requires them to be repeatedly boxed and unboxed the costs can add up quite rapidly; so you should be aware of boxing and unboxing when you are profiling your application.

So the only common base of both Firefighter and Administrator is Object at the moment (remember, everything is ultimately derived from Object). That seems a bit low level, but it is all we have to go on for now, so we’ll make do.

Example 4-17 shows our first pass at a FireStation.

Example 4-17. FireStation class

class FireStation
{
    List<object> clockedInStaff = new List<object>();

    public void ClockIn(object staffMember)
    {
        if (!clockedInStaff.Contains(staffMember))
        {
            clockedInStaff.Add(staffMember);
        }
    }

    public void RollCall()
    {
        foreach(object staffMember in clockedInStaff)
        {
            // Hmmm... What to do?
        }
    }
}

Our ClockIn method is making use of a list of objects to keep track of who is in the station. To do that it is using the generic collection class List<T> we first saw in Chapter 2. Using the List.Contains method, the implementation checks that they weren’t already in the station, and adds them if necessary.

Everything is fine so far. Then we reach the RollCall method. We’re using foreach to iterate over the clocked-in staff, but we don’t actually have a method to call to get their names!

We want a way of indicating that these disparate object types (firefighters, fire chiefs, and administrators) all support giving out their name.

We saw one way of doing that already: we could create a common base class, and move the Name functionality in there. Let’s see what happens if we try to do that.

Practically speaking, we have two completely different implementations of the Name property. We saw that we can model that situation with an abstract base class from which Firefighter and Administrator both derive, both implementing the method in their own way.

Here’s our NamedPerson base with an abstract property for the Name:

abstract class NamedPerson
{
    public abstract string Name
    {
        get;
    }
}

There’s no problem when we implement this on our Administrator:

class Administrator : NamedPerson
{
    public override string Name
    {
        get
        {
            StringBuilder name = new StringBuilder();
            AppendWithSpace(name, Title);
            AppendWithSpace(name, Forename);
            AppendWithSpace(name, Surname);
            return name.ToString();
        }
    }

    // ...
}

Notice how we derived from NamedPerson and added the override modifier to our Name property so that it overrides the abstract method in our base.

That’s fine so far. What about our FirefighterBase? Let’s try doing exactly the same thing:

abstract class FirefighterBase : NamedPerson
{
    public abstract void ExtinguishFire();

    public override string Name { get; set; }

    // ...
}

If we compile that, we get an error:

'FirefighterBase.Name.set': cannot override because 'NamedPerson.Name' does
 not have an overridable set accessor

We run into difficulty because FirefighterBase has both a getter and a setter for the Name property, but our base allows only a getter.

Well, we could work around that with another member to set the name; but as you can see in Example 4-18, it is all getting a bit ugly.

Example 4-18. Mounting evidence that all is not well in our class hierarchy

abstract class FirefighterBase : NamedPerson
{
    public abstract void ExtinguishFire();

    public override string Name
    {
        get
        {
            return RealName;
        }
    }

    public string RealName
    {
        get; set;
    }

    // ...
}

Not only is it ugly, but we have to replace all our object initializers to refer to our new RealName property, so it is making us do unnecessary work, which is never good:

Firefighter joe = new Firefighter { RealName = "Joe" };

Are you feeling uncomfortable with this approach yet? Let’s push on with it just a little bit further, and see what happens if we want to support a second behavior. Say we had a SalariedPerson abstract base that provides us with the contract for getting/setting a person’s salary. We’re going to need to apply that to both the FirefighterBase and the Administrator, to tie in with the billing system:

abstract class SalariedPerson
{
    public abstract decimal Salary
    {
        get;
        set;
    }
}

We’re providing a decimal property for the Salary that must be implemented by any SalariedPerson.

So, what happens if we now try to derive from this class for our Administrator, as shown in Example 4-19?

Example 4-19. The final straw: Our class hierarchy needs a rethink

class Administrator : NamedPerson, SalariedPerson
{
    private decimal salary;
    public override decimal Salary
    {
        get
        {
            return salary;
        }
        set
        {
            salary = value;
        }
    }
    // ...
}

Note

C++ developers will be familiar with this syntax for specifying multiple base classes.

Another compiler error:

Class 'Administrator' cannot have multiple base classes: 'NamedPerson' and
'SalariedPerson'

C# Does Not Support Multiple Inheritance of Implementation

This is a pretty fundamental roadblock! You cannot derive your class from more than one base class.

When the designers of .NET were thinking about the platform fundamentals, they looked at this issue of multiple inheritance and how they’d support it across multiple languages, including C#, VB, and C++. They decided that the C++ approach was too messy and prone to error (particularly when you think about how to resolve members that appear in both base classes with the same signature). The implications of multiple inheritance were probably just too difficult to come to grips with, and therefore were unlikely to bring net productivity gains. With that view prevailing, single inheritance of implementation is baked into the platform.

Note

In more recent interviews, the .NET team has reflected that perhaps there might have been a way of allowing multiple inheritance of implementation, without introducing all the complexity of C++ multiple inheritance. That’s the benefit of 20/20 hindsight; we (or our children) will just have to wait until the next platform generation and see how the argument goes then.

So are we really stymied? No! While we can’t support multiple inheritance of implementation, we can support multiple inheritance of interface.

C# Supports Multiple Inheritance of Interface

With our abstract base classes in this example, we’re not really trying to provide a base implementation for our objects at all. We’re trying to mark them as supporting a particular contract that we can then rely on in our client code.

C# provides us with a mechanism for doing exactly that: interface. Let’s rewrite our NamedPerson and SalariedPerson classes as interfaces instead, as shown in Example 4-20.

Example 4-20. Defining interfaces

interface INamedPerson
{
    string Name
    {
        get;
    }
}

interface ISalariedPerson
{
    decimal Salary
    {
        get;
        set;
    }
}

We use much the same syntax as we do for a class definition, but using the keyword interface instead.

Notice also that we dropped the abstract modifier on the members; an interface is implicitly without implementation. There are no accessibility modifiers on the members either; an interface member is only ever allowed to be public.

The only other change we’ve made is to prefix our interface name with an I. This is not a rule, but another one of those naming conventions to which most people conform.

We can now implement those interfaces on our Administrator, as shown in Example 4-21.

Example 4-21. Implementing interfaces

class Administrator : INamedPerson, ISalariedPerson
{
    public decimal Salary
    {
        get;
        set;
    }

    public string Name
    {
        get
        {
            StringBuilder name = new StringBuilder();
            AppendWithSpace(name, Title);
            AppendWithSpace(name, Forename);
            AppendWithSpace(name, Surname);
            return name.ToString();
        }
    }
    // ...
}

And we can implement them on our FirefighterBase, as shown in Example 4-22.

Example 4-22. The same interfaces in a different part of the class hierarchy

abstract class FirefighterBase : INamedPerson, ISalariedPerson
{
    public string Name
    {
        get;
        set;
    }

    public decimal Salary
    {
        get;
        set;
    }

    // ...
}

Notice that we can happily implement the setter on our FirefighterBase, even though the interface only requires a getter. The restrictions on how you implement the interface—as long as you conform to the contract it specifies—are much looser than those on overrides of a base class. Also, C# doesn’t allow you to use the simple property syntax to define virtual properties or their overrides, but there is no such restriction when you’re implementing an interface. So we’ve been able to use simple property syntax here rather than having to implement using full-blown properties.

We can now make use of this interface in our FireStation class. Instead of a list of objects, we can use a list of INamedPerson, and call on the Name property in our RollCall method, as shown in Example 4-23.

Example 4-23. Modifying the FireStation class to use an interface

class FireStation
{
    List<INamedPerson> clockedInStaff = new List<INamedPerson>();

    public void ClockIn(INamedPerson staffMember)
    {
        if (!clockedInStaff.Contains(staffMember))
        {
            clockedInStaff.Add(staffMember);
            Console.WriteLine("Clocked in {0}", staffMember.Name);
        }
    }

    public void RollCall()
    {
        foreach (INamedPerson staffMember in clockedInStaff)
        {
            Console.WriteLine(staffMember.Name);
        }
    }
}

Note

If you’ve been following through the code in Visual Studio (which I thoroughly recommend), you’ll also need to change your object initializers back to this form:

Firefighter joe = new Firefighter { Name = "Joe" };

If we compile and run, we get the output we hoped for—a roll call of everyone in the station:

Clocked in Joe
Clocked in Bill
Clocked in Harry
Clocked in Mr Arthur Askey
Joe
Bill
Harry
Mr Arthur Askey

Deriving Interfaces from Other Interfaces

Interfaces support inheritance too, just like classes. If you want, you could create a named, salaried person interface like this:

interface INamedSalariedPerson : INamedPerson, ISalariedPerson
{
}

What happens if you have conflicting names? Imagine the interface ISettableNamedPerson:

interface ISettableNamedPerson
{
    string Name
    {
        get; set;
    }
}

What happens if we implement both INamedPerson and ISettableNamedPerson on our FirefighterBase?

abstract class FirefighterBase : INamedPerson, ISettableNamedPerson, ISalariedPerson
{
    // ...
}

The answer is that everything is just fine! Each interface requires that we implement a string property called Name; one requires at least a getter, the other a getter and a setter.

When we access the property through the relevant interface, it can resolve correctly which member we meant; there’s no requirement for a separate implementation for each interface.

But what if that was actually wrong? What if our Name property on INamedPerson had entirely different semantics from the one on ISettableNamedPerson? Let’s suppose that one is intended to allow only letters and numbers with no spaces and the other is just our freeform “any old text” implementation with which we are familiar.

Whenever our client expects an INamedPerson we need to provide the second implementation, and whenever the client expects an ISettableNamedPerson, the first.

We can do that by explicitly implementing the interfaces.

Explicit Interface Implementation

To explicitly implement a particular member of an interface, you drop the accessibility modifier and add the interface name as a prefix, as shown in Example 4-24.

Example 4-24. Explicit interface implementation

class AFootInBothCamps : INamedPerson, ISettableNamedPerson
{
    private string settableName;

    string INamedPerson.Name
    {
        get
        {
            Console.WriteLine("Accessed through the INamedPerson interface");
            return settableName;
        }
    }

    string ISettableNamedPerson.Name
    {
        get
        {
            return settableName;
        }
        set
        {
            Console.WriteLine(
            "Accessed through the " +
            "ISettableNamedPerson interface");

            if( settableName != null && settableName.Contains(" ") )
            {
                // You can't set it if it contains the space
                // character
                return;
            }
            settableName = value;
        }
    }
}

Example 4-25 shows how we’re going to access them from our main function.

Example 4-25. Calling different interface implementations of the same member name on the same object

class Program
{
    static void Main(string[] args)
    {
        AFootInBothCamps both = new AFootInBothCamps();

        ISettableNamedPerson settablePerson = both;
        INamedPerson namedPerson = both;

        settablePerson.Name = "hello";

        Console.WriteLine(settablePerson.Name);
        Console.WriteLine(namedPerson.Name);

        Console.ReadKey();
    }
}

Notice how we’re creating our object, and then providing two additional references to it: one through a variable of type ISettableNamedPerson and one through INamedPerson.

We then call on the Name property through each of those interfaces, and get the following output:

Accessed through the ISettableNamedPerson interface
hello
Accessed through the INamedPerson interface
hello

But what if we try to access it through a reference typed to the class itself?

Console.WriteLine(both.Name);

Add the following line to the main function and compile, and we get a compiler error!

'AFootInBothCamps' does not contain a definition for 'Name' and no extension
 method 'Name' accepting a first argument of type 'AFootInBothCamps' could be
 found (are you missing a using directive or an assembly reference?)

We’ve seen that error before; it means we’re trying to talk to a member that doesn’t exist. What’s happened is that the members that are explicitly implemented exist only if we are accessing them through the relevant interfaces.

However, as long as we explicitly implement one of the two (or two of the three, or however many we’re stuck with), we can choose one interface as our “default” and implement it using the regular syntax, as shown in Example 4-26.

Example 4-26. Implementing one of the interfaces implicitly

class AFootInBothCamps : INamedPerson, ISettableNamedPerson
{
    private string settableName;

    // Regular implementation syntax
    public string Name
    {
        get
        {
            Console.WriteLine("Accessed through the INamedPerson interface");
            return settableName;
        }
    }

    string ISettableNamedPerson.Name
    {
        get
        {
            return settableName;
        }
        set
        {
            Console.WriteLine("Accessed through the ISettableNamedPerson "
                              + "interface");
            if( settableName != null && settableName.Contains(" ") )
            {
                // You can't set it if it contains the space
                // character
                return;
            }
            settableName = value;
        }
    }
}

Now we can compile and run, and the default implementation for our class is the one for the INamedPerson interface:

Accessed through the ISettableNamedPerson interface
hello
Accessed through the INamedPerson interface
hello
Accessed through the INamedPerson interface
hello

Note

In real life, you don’t often come across this need for explicit interface implementation. If you have control over all the code in the application, you should avoid designing in a clash where the names are the same but the semantics are different. Like overloads or overrides with different meanings, it surprises other developers.

The .NET Framework contains a few examples where it uses explicit interface implementation to hide the interface members from the public API of a class, even though there is no clash. The authors are unconvinced that this improves matters.

More often, you will come across this usage where you don’t have control of the code—with two third-party libraries, for instance, both of which declare interfaces with different semantics but a clash of names. Even then, this is not a problem unless you happen to need to implement both interfaces on one class. Even rarer!

Right, let’s go back to our FireStation class for a minute, and imagine an interface we could create to formalize the contract for clocking in: our billing system might define this contract for us so that we can plug into it.

As it happens, our FireStation provides an implementation which can ClockIn named people, but our billing system’s IClockIn contract is much more generic—it can clock in anything of type Object, as we had in our original implementation:

interface IClockIn
{
    void ClockIn(object item);
}

We can now implement IClockIn on our FireStation, as shown in Example 4-27.

Example 4-27. Implementing the IClockIn interface

class FireStation : IClockIn
{
    List<INamedPerson> clockedInStaff = new List<INamedPerson>();

    public void ClockIn(INamedPerson staffMember)
    {
        if (!clockedInStaff.Contains(staffMember))
        {
            clockedInStaff.Add(staffMember);
            Console.WriteLine("Clocked in {0}", staffMember.Name);
        }
    }

    public void RollCall()
    {
        foreach (INamedPerson staffMember in clockedInStaff)
        {
            Console.WriteLine(staffMember.Name);
        }
    }

    public void ClockIn(object item)
    {
        // What to do here
    }

}

Our original ClockIn method is unchanged, and we’ve added a new overload that takes an object, and therefore matches the requirement in our interface. But how do we implement that new method? We want to check that the person being clocked in is an INamedPerson, and if it is, perform our usual operation. Otherwise, we want to tell the user that we can’t clock him in.

In other words, we need a manual check for the type of the object.

The Last Resort: Checking Types at Runtime

C# provides us with a couple of keywords for checking the type of an object: as and is.

Here’s how we can use them in our ClockIn implementation:

public void ClockIn(object item)
{
    if (item is INamedPerson)
    {
        ClockIn(item as INamedPerson);
    }
    else
    {
        Console.WriteLine("We can't check in a '{0}'", item.GetType());
    }
}

Notice how we are using the type name to check if the item is of that type. And then we call our other overload of ClockIn by explicitly converting to a reference of our INamedPerson type, using as.

It checks to see if our object would be accessible through a reference of the specified type. It looks at the whole inheritance hierarchy for the object (up and down) to see if it matches, and if it does, it provides us a reference of the relevant type.

What if you don’t bother with the is check and just use as? Conveniently, the as operation just converts to a null reference if it can’t find a suitable type match:

public void ClockIn(object item)
{
    INamedPerson namedPerson = item as INamedPerson;
    if(namedPerson != null)
    {
        ClockIn(namedPerson);
    }
    else
    {
        Console.WriteLine("We can't check in a '{0}'", item.GetType());
    }
}

This is the form in which you most often see a test like this, because it is marginally more efficient than the previous example. In the first version, the runtime has to perform the expensive runtime type checking twice: once for the if() statement and once to see whether we can actually perform the conversion, or whether null is required. In the second case, we do the expensive check only once, and then do a simple test for null.

Summary

So far, we’ve seen how to create classes; to model relationships between instances of those classes through association, composition, and aggregation; and to create relationships between classes by derivation. We also saw how virtual functions enable derived classes to replace selected aspects of a base class.

We saw how to use protected and protected internal to control the visibility of members to derived classes. Then, we saw how we can use either abstract classes and methods or interfaces to define public contracts for a class.

Finally, we looked at a means of examining the inheritance hierarchy by hand, and verifying whether an object we are referencing through a base class is, in fact, an instance of a more derived class.

In the next chapter, we are going to look at some other techniques for code reuse and extensibility that don’t rely on inheritance.

Get Programming C# 4.0, 6th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.