Incremental Java
Overriding Methods

Extending a Class

Suppose you have a class. This could have been written by you, or it could have been written by someone else. You like the class. It does what you want, mostly.

But you want to add some new methods to it, or new instance variables, or both. You may even want to change the way the methods in the class behave.

If these are the kinds of changes you want to make, then you don't have to rewrite a new class. Instead, you can extend the class by writing a child class. This is what inheritance is about. It's about reusing code, instead of writing it again from scratch.

When you write a child class, you can make the following changes:

You inherit the following from the parent class. This means, the child class has all of the public methods that the parent class has. It has all of the instance variables. The only unusual aspect is that, within child class method definitions, you can't directly access parent class instance variables. For example, if the parent had a height instance variable, child class method definitions wouldn't be able to access this directly.

The instance variable is there, but the only way to access it is through the public methods of the parent class. (The other way is to make the instance variables of the parent class public, but in general, this is not an option. If someone else did write the parent class, you won't be able to modify it, in most cases).

Overriding Parent Class Method

Suppose we wanted to write a child class of Rectangle. This class is called FramedRectangle. You can set the height and width as usual, but there is a frame of length 1 all the way around the Rectangle object. For example, if the width was 7 and the height was 4, then with the frame, the total width is 9 and the total height is 6 (the frame adds 2 units to the width and height).

The parent class defines getPerimeter() as:

public int getPerimeter()
{
   return 2 * ( height + width ) ;
}
In the child class, we redefine getPerimter() as:
public int getPerimeter()
{
   return 2 * ( super.getHeight() + super.getWidth() + 4 ) ;
}
We have overriden the getPerimeter() method from the parent class. To override it, we must have the identical method signature, but put in a new method body.

super is a way for us to call the method from the parent class (which is also called the superclass). We can leave super off, and just use getHeight() and getWidth(). However, this may cause problems if we also override the getHeight() and getWidth() method in FramedRectangle.

We assume the getHeight() method in FramedRectangle adds 2 to the height from getHeight() method in Rectangle. For example:

public int getHeight()
{
   return super.getHeight() + 2 ;
}
By calling super.getHeight(), we use the version provided in Rectangle, rather than the one that's defined in FramedRectangle.

Seeing the Differences

Let's see how overriding affects objects.
public static void main( String [] args )
{
   Rectangle r = new Rectangle( 3, 5 ) ;
   FramedRectangle f = new FramedRectangle( 3, 5 ) ;

   System.out.println( "r's perimeter is: " + r.getPerimeter() ) ;
   System.out.println( "f's perimeter is: " + f.getPerimeter() ) ;
}
This prints out:
r's perimeter is 16
f's perimeter is 24
If we hadn't overridden getPerimeter() in FramedRectangle, it would have printed out 16 in both cases, because FramedRectangle would use the getPerimeter() defined in Rectangle.

Picking Methods

Suppose you have the following method call:
   foo.doSomething() ;
Assume foo has type Foo.

The simple rule for deciding which doSomething() gets run is the following.

Basically, you check to see if your class defined this method, if not, you go up to your parent, parent's parent and so forth. All of these classes are your ancestor classes. If none of your ancestor classes define doSomething(), then the Java compiler prints an error message. It must be defined in some ancestor class.

The problem of which version of doSomething() gets a little more complicated, and we'll see how it's resolved in the next section.