is that, if, at a later date, you find that LinkedLists don't work the way you want (or whatever), and say ArrayLists are what you really need, it's only a one line change to swap out an ArrayList for a LinkedList:
This becomes even more important when you consider the public API of a class. By using the interface, you can easily make changes without affecting the future use of that class. If you program against the implementation, it may be very hard (or impossible) to change later.
Something about this has been bothering me. I understand the logic of the answer, and why it might turn out in the future to be the right decision to use List now, but to use this as a reason against programming to the implementation doesn't sound right...
I mean, what is a "native java class" if not it's implementation? If you are going to avoid programming to the implementation because the implementation might change, then what's the point of having the implementation in the first place?
This all seems too obvious, so maybe I am missing something.
I don't think you're missing anything. The argument that the public API of LinkedList might change is a specious one, as Sun has always been very careful to avoid this. But replace "LinkedList" with "SomeClassFromAnOpenSourceProject", where there isn't the same commitment to backwards compatibility, and you can start to see the value. If there's an interface, especially a standardized one like List, use it if you can.
Here's something a little more subtle. Imagine that you write a routine processAllItems() that calls process() on each item in a List. When you write processAllItems(), you have a LinkedList that you want to pass to it. Do you make it take a List or a LinkedList as an argument? Well, if you use LinkedList, then
1) you'll have to change processAllItems() if you want to start using an ArrayList instead;
2) you'll have to create a LinkedList anywhere you want to call processAllItems()
If, on the other hand, you use List, then you have much more freedom in the code that calls processAllItems(). Imagine that this routine ends up being called in 100 different places -- imagine how nice that flexibility would be!
This kind of design principle can be hard to appreciate in small projects, but as you get involved in larger, longer-lived, more complex work, they become enormously important.
In conclusion then the original premise specifically about LinkedLists is inaccurate. A List reference is not inherently recommended over a LinkedList reference. Alhough there are reasons why you would sometimes do it, insulating yourself from the implementation of LinkedList isn't one of those reasons.
posted 11 years ago
This all touches upon something I have been struggling with for a while. I understand the how, but not always the why.
OK, an interface just contains method signatures, not method bodies. If you write a class that implements that interface, then you must provide your own implementation of the method. Furthermore, that implementation must have some code in it if you want the method to do anything. So far so good.
OK, you can use the interface as a reference type, which means declaring a variable of the type of the interface, and have it reference (point to) an object, an instance of the class that implements the very same interface. By doing so, you can use the "interface type" to call methods that the interface has signatures for. You think of the object as an interface type.
This is where I am getting hung up. If the interface just contains a method signature, and if the implementing class has the imlementation of the method, and if the class already has the method, then what is the point of declaring a reference variable of the type of the interface, why wouldn't you just use a "class reference"?
Consider the case discussed here, of having a List variable referencing a LinkedList (or ArrayList for that matter) object. I don't get the point, seeing as how it is LinkedList that implements the methods.
Ok, as I write this, a light starts to flicker. hmm the wheels are turning... How does this sound?
OK, the only thing I can thing of is that an interface kind of functions somewhat like an abstract superclass with abstract methods, where any concrete subclass must implement (override) these methods. In this sense, implementing an interface and overriding it's method is kind of like extending an abstract class. And there is no point in using an interface as a datatype unless you intend to write code that applies to more than one type of object.
So to summarize, the main reason for using an interface as a data type, at least when it comes to implementing classes that are well defined and here to stay, is akin to the reason why you use polymorphism.
That is basically it, yes. Interfaces have some extra benefits because a single class can implement many interfaces, but extend only one class, so interfaces give you much more flexibility. If you're designing an API which will ask other folks to implement some type, you should STRONGLY prefer making that type be an interface rather than an abstract class, as it allows them to build their implementation using a wider range of options.
But I'm not sure you appreciate all the neat stuff that these tools can do for you. Check out the JDBC API as an excellent example. Almost everything is an interface: Connection, Statement, ResultSet, and many more. There are virtually no concrete classes. Why? Because someone can implement a driver for any database as long as they conform to those interfaces, and as long as you work only with the interfaces and never use the actual class names, your program will work unchanged against a wide range of totally different databases. Think about how you'd implement Connection if it were a class, even an abstract base class. Now think of the freedom you get because Connection is an interface.
Thanks. I think I understand the intent of the JDBC example, it's all about being independant of the actual database you are using (Access, mySQL, Oracle, etc.) as long as you have the right driver.
The Sun Java tutorial has an example that just had me scratching my head. http://java.sun.com/docs/books/tutorial/java/IandI/usinginterface.html where they have a simple interface called Relateable, and shown one class that implements it. I am thinking there is no value in what they have done, unless there are other classes beside RectanglePlus that also implement the Relateable interface, Further more these other classes would also have to implement an isLargerThan method, and each of these other methods would have to have the Relateable type as a parameter, then do it's own typecasting of the Relateable object back into it's original type, in order to do the comparison. Then whatever main application used these classes, they could treat them equally by referencing them as Relateable.
That's a damn odd example, actually, because it's so close to a real example, but for some reason they use this made-up interface. The real example from the API is java.lang.Comparable, which contains not "isLargerThan()", but "compareTo()", which likewise returns -1/0/1, and likewise is always implemented to cast the parameter to the implementing type.
But Comparable.compareTo() is extremely useful, because it allows a List or array to be sorted using a generic method. There's a static sort() method in the java.util.Arrays class that will sort any kind of Object, as long as it implements Comparable (as do many API classes like String and Integer), and there are similar methods for sorting List classes in the java.util.Collections class.