Next Previous Up Top


4 Class Relationships

4.4 An Inheritance Example


4.4 An Inheritance Example


Suppose we have a class IntQueue, which provides objects that can store a queue of ints: a queue is a storage device that allows new items to be added at the back and removed from the front[18]. The class might be outlined as:

class IntQueue
{
	public void addback(int x) { ... }
	public int removefront() { ... }

	private int[] items ;
}

This queue has a data structure, an array of integers, and two methods; one to add an integer to the back of the queue and one to remove an integer from the front of the queue[19].

Now suppose we want to implement an IntDequeue, which is a queue of integers that can have items added and removed from both the back and front of the queue (usually called a 'double-ended queue', hence dequeue). We could implement a completely new class:

class IntDequeue
{
	public void addback(int x) { ... }
	public int removeback() { ... }
	public void addfront(int x) { ... }
	public int removefront() { ... }

	private int[] items ;
}

but in doing so we notice that it shares quite a bit of similarity with the IntQueue class. Rather than create the Dequeue class from scratch, we could make it an extension or subclass of IntQueue, inheriting the methods and variables declared by that class:

class IntDequeue extends IntQueue
{
	public int removeback() { ... }
	public void addfront(int x) { ... }
}

The line

class IntDequeue extends IntQueue

states that IntDequeue is an extension of IntQueue. IntDequeue only needs to provide two new public methods in order to extend the IntQueue class and provide the public interface needed by dequeues.

Having got this far, a problem appears which must be addressed immediately. The IntQueue class defines its data structure as:

private int[] items ;

This dictates that the data variable items is private to the IntQueue class and can only be accessed by methods declared in the IntQueue class; this is encapsulation being properly enforced. The problem for us with this inheritance-based implementation of IntDequeue is that the methods added by the IntDequeue subclass need to access items but they cannot even though the IntDequeue objects contain that variable. Clearly, not having this problem is important!

There is a third scope type, protected, that is designed exactly for this situation. We make the scope category of the items variable protected rather than private:

class IntQueue
{
	public void addback(int x) { ... }
	public int removefront() { ... }

	protected int[] items ;
}

Protected opens up the encapsulation just a little so as to allow subclass methods access to variables declared by a superclass whilst still preventing anything from outside either class gaining access. With this change in place we can now create a usable IntDequeue class, noting that the declarations in class IntQueue do not need to be copied or edited in order to do so.

This example highlights the rules of encapsulation. A private variable or method is only accessible to methods declared in the same class. Inheritance does not violate the encapsulation rules, so even though a subclass inherits private variables and methods, none of the methods declared by the subclass can access them directly. If access is needed then either indirect access can be obtained by calling an inherited public or protected method or the variable or method can be made protected.

One other observation about classes IntQueue and IntDequeue is appropriate at this point. Both classes deal with queues of integers, a fact which is reflected in their names. What if we want to have queues holding other types of value, such as floating point numbers? Well, we could declare new classes called FloatQueue and FloatDequeue. But do we really want to do this? Every time a queue or dequeue is needed to store some further type of value, a new queue or dequeue class is needed. This could rapidly get out of hand and a better solution is needed -- ideally we only want to write one queue class and one dequeue class.

As yet we don't have enough background information about object-oriented programming and Java to address this problem. We will return to this issue in later chapters and, in particular in Chapter 19, Page 379, we will see a more complete solution.


[18] Queues will be covered fully in Chapter 19, Page 379 and Dequeues in Chapter 20, Page 419.
[19] In this example we will ignore problems such as the queue being empty or full, but for a real Queue class these are important issues, as will be seen in Chapter 19.

Copyright 1997 Russel Winder and Graham Roberts

Last updated: 6 Oct 1997