Expand
Minimize

Inheritance

Another big word for a simple concept. To help explain inheritance, we'll go back to our beer example. Say we want to define a new class to represent a pint of an imported French beer. This class would have all the variables and methods of the normal beer class, but it would have the following additional information:

  • A variable representing the price of the beer
  • Two methods to set and get the price of the beer

(We need this information because we are students; everyone knows the price of Harp, but we would like to know the price of this expensive beer before we order it!)

It would be rather tedious to define a new class, FrenchBeerType which had all the variables and methods of BeerType plus the few extra we needed. Instead, we can define FrenchBeerType to be a subclass of BeerType.

A subclass is a class definition which derives functionality from another class definition.

What this means is that we only need to define the additional information that the FrenchBeerType class has.

So, we create a new class, FrenchBeerType, and tell our compiler that it is a subclass of BeerType. In the class definition, we would include only the following information:

  • A variable BeerPrice
  • A method SetBeerPrice
  • A method GetBeerPrice

We do not need to include any information about BeerName for example; all this is automatically inherited. This means that FrenchBeerType has all the attributes of BeerType plus a few additional ones. All this talk of beer...

Counters, Counters, Counters...

Back to the counter example then! The counter we had in the last section is fine for most counting purposes. But say in a program we require a counter that can not only be incremented, but can be decremented too. Since this new counter is so similar in behaviour to our previous counter, once again would be mad to define a brand new class with everything that Counter has plus a new method. Instead, we'll define a new class ReverseCounter that is a subclass of Counter. We'll do this in Java.

class ReverseCounter extends Counter
{
    public void DecrementCounter(void)  {
        MyCounter--;
    }
}

The extends clause indicates the superclass of a class definition. A superclass is the "parent" of a subclass; in our beer analogy, BeerType is the superclass of FrenchBeerType, so if we were defining this in Java we would use class FrenchBeerType extends BeerType. We are simply saying that we want ReverseCounter to be a subclass of Counter. In Java, when we define a brand new class that is not a subclass of anything (as we did when we defined Counter) we use the superclass Object to indicate we want the default superclass.

We have defined ReverseCounter to be a subclass of Counter. This means that if we instantiate a ReverseCounter object, we can use any method that the class Counter provided, as well as the new methods provided. For example, if i is an object of the ReverseCounter class, then we can both increment it and decrement it; i.IncrementCounter(); and i.DecrementCounter; respectively.

Inheritance is a powerful tool. Unlike our simple example, inheritance can be passed on from generation to generation; we could define a class SuperDuperReverseCounter for example, that is a subclass of ReverseCounter which could provide added variables or methods.

Bugs, bugs, bugs...

If you tried to compile the above example and found it wasn't compiling, don't worry! There is a semi-deliberate mistake left in the code, which I am very usefully going to use to stress a point.

When defining a class you must consider subclasses.

When we defined the Counter class we didn't even know what a subclass was, so we could be forgiven for breaking this rule. If we go back to how the class was defined:

class Counter extends Object  {
    private int MyCounter;

    ...
    ...
}

We can see that the variable MyCounter is defined to be of type private. In Java, this means that the variable becomes very, very private indeed; in fact, it is only accessible from inside the class from which it is defined. It is not available to any other class, including its derived classes. So when we reference MyCounter from inside the ReverseCounter the Java compiler will kick up a fuss, since we don't have access to that variable.

We should have realised at the time of writing the Counter class that subclasses might need to get at this variable too. To fix this, all we have to do is change the definition of MyCounter to:

    protected int MyCounter;

A variable with a protected qualifier means that it can be accessed from within the class in which it is defined, as well as all subclasses of this class. This is appropriate in this case.

Next: Conclusion.


2011 Contact