This tutorial was taken directly from my
recent blog postYou've heard this before, no doubt. And, I'm sure along with it came a long explanation. So, I'm not going to bore you with words. I'm going to show you a concrete example of exactly why it's important, using the Java Collections API.
Let's say you're coding along and decide you need to use a queue to help implement your design. No problem. You just call up the
JavaDocs and find the
Queue interface. Under
All Known Implementing Classes, you see
LinkedList and decide, "That will do." Great. You've got your queue. Let's say you declare it like so
CODE
public class SomeClass
{
protected LinkedList<String> queue = new LinkedList<String>();
...
}
Now you can use it like a queue and do things like this:
CODE
queue.offer("first"); // inserts "first" into queue
queue.offer("second"); // inserts "second" into queue
queue.poll(); // removes and returns head of queue: "first"
queue.peek(); // returns but does not remove head of queue "second"
Pretty cool. But there's a problem. You knew there would be, right?
Let's assume someone extends your class. Their class will have access to the queue because you marked it protected, which is what you want (in this scenario). But because you made the queue a
LinkedList reference, the subclass can do things like this:
CODE
// continuing from above example
queue.peek(); // returns but does not remove head of queue" "second"
queue.add(0, "third"); // Hey, what's it doing!?
queue.poll(); // returns and removes head of queue: "third"
So what happened? Well, this code used the
add method to add the
String "third" to the head of the queue, which is not normal queue (FIFO: First In First Out) behavior. Why was this allowed to happen? Because we programmed to an implementation, not an interface. We made the queue variable a
LinkedList reference rather than a
Queue reference. And
LinkedList implements many interfaces, including
List, which is where the
add method came from. You might be saying to yourself, "Why not just make queue private and then create
offer,
pool, and
peek delegate methods? You could do that...
CODE
public boolean offer(String s)
{
return queue.offer(s);
}
public String poll()
{
return queue.poll();
}
...
...etc
...but it's much more simple to do this:
CODE
public class SomeClass
{
protected Queue<String> queue = new LinkedList<String>(); // now a Queue reference variable
...
...
}
This will ensure that only the methods of the Queue interface are acessible.
This example might seem contrived, but I hope it demonstrated the point of interface over implementation.
This post has been edited by Programmist: 19 Dec, 2007 - 08:48 PM