Lecture 27

Subclassing

When the definition of one class is very similar to the definition of another, it is a good idea to examine their relationship.

For example, consider the notions of classes A and B. If it can be said
that every instance of B **is-a** possible instance of A, then this
**is-a** relationship is an indication that class B can be defined
simply by extending class A.

The java syntax for this is:

public class B extends class A { /* definition of class B in excess of class A's definition */ }By using the

As an example, let's consider a simple Parallelogram class, defined below.

public class Parallelogram { protected int length, width, angle; protected Parallelogram() { // provided for subclasses this(0,0,0); } public Parallelogram(int l, int w, int a) { length = l; width = w; angle = a; } public int circumference() { return length + width + length + width; } }

We have provided a **default constructor** for Parallelogram,
namely `Parallelogram()`

. This constructor operates by calling
the main constructor, passing it 0 for its parameters. The syntax for
one constructor calling another is **this(...)**, where the parameters
must match the desired constructor.

This default
constructor is not useful in general, but could be used by subclasses of
Parallelogram. We therefore mark it as **protected** so it is available
only to subclasses of Parallelogram.

Suppose we now need a Rhombus class. Because every
Rhombus **is-a** Parallelogram, we can obtain Rhombus by extending
Parallelogram.

public class Rhombus extends Parallelogram { protected Rhombus() { // provided for subclasses this(0,0); } public Rhombus(int size, int angle) { super(size, size, angle); } } |
public class Rhombus extends Parallelogram { protected Rhombus() { // provided for subclasses this(0,0); } public Rhombus(int size, int angle) { /* Default super() constructor called automaticaly because we didn't call any super constructor ourselves. */ length = size; width = size; angle = a; } } |

Using the super constructor | Using the default super constructor |

When one class extends another, the first thing that must happen in the
subclass is initialization of its superclass, by calling **some**
constructor in the superclass. On the left, we have explicitly called
the Parallelogram constructor that accepts 3 integer parameters. On the
right, we did not call any super constructor, so the default one -- the
one with no parameters -- is automatically called for us.

Subclassing allows us to reuse code, which saves us time. For example,
although Rhombus does not define `circumference()`

directly,
it inherits the implementation from its superclass (Parallelogram).

Now suppose we want to introduce a square. Every
square **is-a** paralellogram. But it is also true that
every square **is-a** rhombus. We gain more reuse by extending Rhombus,
thus:

public class Square extends Rhombus { protected Square() { // for subclasses this(0); } public Square(int size) { super(size, 90); } }

We make a square by making a rhombus whose angle is 90 degrees.

**Think about:**

- How you would subclass Square to make a unit-square: a square whose sides are all 1 unit in length?
- What would our system of shapes look like if we had subclassed Parallelogram to obtain Rectangle instead of Rhombus? Where would Square fit in? How would we introduce Rhombus later?

Last modified 09:36:45 CST 05 November 2002 by Ron K. Cytron