Programming to Interfaces
Yet another article from the archives. Hope it’s useful.
There is a common Object Oriented axiom that says “Program to the Interface and not to the Implementation”. But what does that mean and why is it useful?
Concrete Shoes
Let’s say that we have a class that calculates the number of Strings that begin with S in a list:
class Begins {
public static int calcBeginsWithS(ArrayList words) {
Iterator iter = words.iterator();
int answer = 0;
while(iter.hasNext()) {
String word = (String) iter.next();
if(word.startsWith("S")) {
answer++;
}
}
return answer;
}
}
This function works great as long as we’re only working with ArrayList
. But an ArrayList
is a concrete class; it’s an implementation of the List
interface. There’s nothing in our function that specifically requires using ArrayList
and so we’ve crippled what we can do to this class and how it can be used. We’ve prevented ourselves from using this in a number of other cases for no real reason.
Talk to the Interface
Someone may want to call this function with a String[]
, but won’t be able to until they get that String[]
into an ArrayList. But that’s an extra object you have to create, along with shoving all of the String
objects into it, that you’ll just throw away afterwards. But if we change our method to accept List
instead:
public static int calcBeginsWithS(List words)
and we have a String[] words
, we can call it like this:
int count = Begins.calcBeginsWithS(Arrays.asList(words));
We might also need to update legacy code that uses Vector
. (Remember those!) Sun has discouraged the use of Vector
, but they have retrofitted the List interface onto it. If your function accepts List
instead of ArrayList
, you could use it with legacy code that uses Vector
too.
But why stop there? If you used:
public static int calcBeginsWithS(Collection words)
You can now use this method with Set
and Queue
and Stack
and it will still work. We’ve made the function support every Collection type in the language and it really didn’t cost us a thing. I’ve personally run into libraries a number of times that only supported List but, with one simple interface change, could have supported the Set that I needed to use with it.
So, when you code something, be sure to ask yourself “Do I really need to code this to a concrete class, or can I use an interface instead?” Walk up that interface tree and see what’s the highest level interface your code can support. You may be able to make your code more powerful by just changing a single word.