Suppose we sometimes want to have Queues of Strings that at any point in time can tell us how many elements are currently in the Queue. Once again, we want to do this without changing the original Queue class. This might be because we only occasionally need this new functionality, or it might be because we don't have the right to change Queue, or because we don't actually have access to the source code. Here's how we might do it.
public class MyQueue extends CountingQueue
{
public void enqueue(String s)
{
super.super.enqueue("my:"+s); ← Not actually legal!!
}
...
}
By doing this, the "CountingQueue" functionality that I was
supposed to have inherited has been messed up! Why? Because
something has been enqueued but not "counted". Moreover, it's
only possible to know whether or not this has messed something
up, and in what way it's been messed up, if you are intimately
familiar with the implementation of CountingQueue, and
that's the very thing we don't want in object oriented
programming!
If you don't think this is bad, consider the following: what
if the person in charge of CountingQueue decides to
override empty() so that it checks whether count
is zero to provide it's true/false answer. From the
CountingQueue guy's perspective, this should be thoroughly
safe and not break other people's code. But now MyQueue will
break in an unanticipatable way: done() for MyQueue's will
give incorrect results.
That's why super.super, or something like it, is not allowed!
protected accessBut how do we define that method? The super class Queue does not provide public methods that allow us to implement this functionality, and since the fields of Queue are private, we can't implement it for ourselves. From the perspective of the implementer of class Queue, you would say that it's impossible to anticipate everything someone would want to do with a Queue and to provide public methods that make all possible operations implementable. That's true. A compromise between strict separation of interface from implementation and a wild west all-fields-are-public approach is to use the
protected access modifier.
When a field is marked "protected", it means that it is
accessible inside the class and any derived classes, but not
from anywhere else. If we change head and tail in Queue to
be protected, implementing PeekaQueue becomes easy.