Reputation: 13486
My question today is not a problem-solving question, but a best-practice theory question. I am getting familiarized with Joda-Time, and I read this in the user guide (http://joda-time.sourceforge.net/userguide.html#Interface_usage):
When working with a Collections interface, such as List or Map you will normally hold your variable as a type of List or Map, only referencing the concrete class when you create the object.
List list = new ArrayList(); Map map = new HashMap();
This struck me as quite an odd statement. In my programming, I've always held the concrete class for my variables unless I'm programming an API of some sort. Does anyone have any helpful material to explain the reasons why it would be preferential to hold the general/abstract class vs the concrete class for your variable type?
To illustrate, I wrote a simple method that I use whenever I need a list of objects as a string separated by commas:
public static <T> String CSV(Collection<T> list) {
boolean first = true;
StringBuilder sb = new StringBuilder();
for(Object e : list) {
if(first)
first = false;
else
sb.append(", ");
sb.append(e.toString());
}
return sb.toString();
}
Here, of course, you must use Collection so you can pass in anything you want, Object[], LinkedList, etc.
But let's say elsewhere I'm storing a set of strings and I want it to be a LinkedHashSet, I would create the variable like this:
LinkedHashSet<String> set = new LinkedHashSet<String>();
or
LinkedHashSet<String> set = new LinkedHashSet<>();
(because of the changes in Java 7)
but according to Joda-Time's user guide, I should do this:
Set<String> set = new LinkedHashSet<String>();
?
I just don't see the advantages. Anyone have helpful input/reading material?
Thanks!
Upvotes: 2
Views: 1983
Reputation: 4970
My general rule of thumb on instantiation is use the most base class that would fit your needs.
What I mean by this is in this case you're using a LinkedHashSet, if you know you are only going to be using methods fulfilled by the contract of Set, instantiate it as a Set. The reason to do this is it makes your code more future proof. For example, if you need to go back and make sure that Set is thread safe, you instantiate the Concurrent class rather than the non-thread safe LinkedHashSet. This way, your downstream code doesn't change, you only need to update the instantiation.
Upvotes: 0
Reputation: 62769
You generally want to use an interface that most closely defines the functionality you need.
Here are some reasons to use Queue over LinkedList:
The last one is a pretty big point for a number of reasons. If you write a method that returns a "Queue", you can expect that it won't be handled inappropriately and you instantly describe to users exactly how their new object can be manipulated. It's not intended to be iterated over as a List, for instance.
This also applies to your own interfaces, you might want to create an interface to expose a subset of functionality for one purpose while exposing a different subset for another purpose... For instance you COULD have the same queue returned to two different callers, one with an "Enqueue" interface and one with a "Dequeue" interface--making it very clear which direction the "Pipe" is supposed to flow.
Upvotes: 0
Reputation: 8229
If you work with Collection
(for example) it doesn't matter, how does this Collection
implemented - you want to use Collection
methods and nothing more.
In this case your code will be pretty agile and you can easily change Collection
implementation. But if basic interface is not enough - use concrete reference.
It is OOP basics - you should to work with abstractions, not with concrete classes if it is possible.
Upvotes: 2
Reputation: 11
If your are writing some code that will be used or modified by others, it s easier to use interfaces and let them choose the best implementation, instead of choosing a concrete type so forcing them to use your type.
Upvotes: 0
Reputation: 39451
Since Java doesn't have type inference (yet), you have to explicitly specify the variable when you define it, and every time you create a new variable based on it. If the type is a concrete class, this means that if you later want to change it, you'll have to go through and change all those declarations as well. A refactoring tool could probably automate it, but it's still a minor annoyance. Using an abstract or interface type allows you to change the concrete type without changing all those declarations.
Overall, I don't think it's a big deal either way.
Upvotes: 0