Reputation: 923
I just making an effort to understand the power of the interfaces and how to use them to the best advantage.
So far, I understood that interfaces: enable us to have another layer of abstraction, separate the what (defined by the interface) and the how (any valid implementation).
Given just one single implementation I would just build a house (in one particular way) and say here, its done instead of coming round with a building plan (the interface) and ask you, other developers to build it as i expect.
So far, so good.
What still puzzles me is why to favor interface types over class types when it comes to method parameters and return values. Why is that so? What are the benefits (drawbacks of the class approach)?
What interests me the most is how this actually translates into code.
Say we have a sort of pseudo mathInterface
public interface pseudoMathInterface {
double getValue();
double getSquareRoot();
List<Double> getFirstHundredPrimes();
}
//...
public class mathImp implements pseudoMathInterface { }
//.. actual implementation
So in the case of getPrimes() method I would bound it to List, meaning any concrete implementation of the List interface rather than a concerete implementation such as ArrayList!?
And in terms of the method parameter would I once again broaden my opportunities whilst ensuring that i can do with the type whatever i would like to do given it is part of the interface's contract which the type finally implements.!?
Upvotes: 2
Views: 334
Reputation: 181149
An important reason to prefer interfaces for formal argument types is that it does not bind you to a particular class hierarchy. Java supports only single inheritance of implementation (class inheritance), but it supports unlimited inheritance of interface (implements
).
Return types are a different question. A good rule of thumb is to prefer the most general possible argument types, and the most specific possible return types. The "most general possible" is pretty easy, and it clearly lines up with preferring interface types for formal arguments. The "most specific possible" return types is trickier, however, because it depends on just what you mean by "possible".
One reason for using interface types as your methods' declared return types is to allow you to return instances of non-public classes. Another is to preserve the flexibility to change what specific type you return without breaking dependent code. Yet another is to allow different implementations to return different types. That's just off the top of my head.
Upvotes: 1
Reputation: 200216
Say you are the creator of a Maven dependency, a JAR with a well-known, well-specified API.
If your method requests an ArrayList<Thing>
, treating it is a collection of Things, but all I have got is a HashSet<Thing>
, your method will twist my arm into copying everything into an ArrayList
for no benefit;
if your method declares to return an ArrayList<Thing>
, which (semantically) contains just a collection of Things and the index of an element within it carries no meaning, then you are forever binding yourself to returning an actual ArrayList
, even though e.g. the future course of the project makes it obvious that a custom collection implementation, specifically tailored to the optimization of the typical use case of this method, is desperately needed to improve a key performance bottleneck.
You are forced to make an API breaking change, again for no benefit to your client, but just to fix an internal issue. In the meantime you've got people writing code which assumes an ArrayList
, such as iterating through it by index (there is an extremely slight performance gain to do so, but there are early optimizers out there to whom that's plenty).
I propose you judiciously generalize from the above two statements into general principles which capture the "why" of your question.
Upvotes: 3
Reputation: 5496
So in the case of getPrimes() method I would bound it to List, meaning any concrete implementation of the List interface rather than a concerete implementation such as ArrayList!?
Yes, this allows the method to later then change what List type it returns without breaking client code that uses the method.
Besides having the ability to change what object is really passed to/returned from a method without breaking code, sometimes it may be better to use an interface type as a parameter/return type to lower the visibility of fields and methods available. This would reduce overall complexity of the code that then uses that interface type object.
Upvotes: 0