Why to keep interface as reference? [duplicate] - java

This question already has answers here:
Type List vs type ArrayList in Java [duplicate]
(15 answers)
Closed 9 years ago.
I have observed in Java programming language, we code like following:
List mylist = new ArrayList();
Why we should not use following instead of above one?
ArrayList mylist = new ArrayList();

While the second option is viable, the first is preferable in most cases. Typically you want to code to interfaces to make your code less coupled and more cohesive. This is a type of data abstraction, where the user of mylist (I would suggest myList), does not care of the actual implementation of it, only that it is a list.

We may want to change the underlying data structure at some point, and by keeping references, we only need to change the declaration.

The separation of Abstract Data Type and specific implementation is one the key aspects of object oriented programming.
See Interface Instansiation

Just to avoid tight coupling. You should in theory never tie yourself to implementation details, because they might change, opposite to interface contract, which is supposed to be stable. Also, it really simplifies testing.
You could view interface as an overall contract all implementing classes must obey. Instead, implementation-specific details may vary, like how data is represented internally, accessed, etc. - the information that you'd never want to rely on.

If you use ArrayList, you are saying it has to be an ArrayList, not any other kind of List, and to replace it you would have to change every reference to the type. If you use List you are making it clear there is nothing special about the List and it is used as a plain list. It can be changed to another List by changing just one line.

Related

What exactly does the Collection keyword mean in java? [duplicate]

This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 8 months ago.
I saw some code in Java that used code similar to
Collection<Cars> carsCollection = new ArrayList<>(); But I am a bit confused about the word Collection.
I have a basic understanding of Collections in general, and how a list or queue is part of the collections but I am having a hard time understanding why they would use Collection<Cars> instead of ArrayList<Cars>. All the information I find on the internet about Collections is how lists and queues use them but I haven't seen much other code that uses the Collections keyword itself, most of them just implement arrays or lists or something else that is a part of the Collections framework. How do you use it or why use it? I tried casting it to an ArrayList like ArrayList<Cars> aList = new ArrayList<>(carsCollection) and it said their was an issue with casting it to an ArrayList.
As people have mentioned Collection is an interface, an interface in Java is a tool for abstraction. So the way to think about it is in terms of generality, where a Collection in this case is the most general term. Then you have, for example List, Map or Set which in turn are more specific abstractions of the idea of a Collection, finally you have the implementations for example ArrayList, HashSet and HashMap.
Generally you want to be as abstract as possible, i.e. using the most general abstraction that still fullfills the requirements that you have on your code.
In your example with Collection<Car> and ArrayList<Car> (which probably ought to be List<Car>), my guess would be that in the case of Collection<Car> that the code doesn't care about the order, because that isn't a requirement of the Collection abstraction, but in the case of the List abstraction it is.
I'd recommend that you read the javadoc for Collection and the other interfaces and implementations.
It is just an interface for a collections alike structures Lists, Sets,Maps etc. It denotes fact that this is a "collection" of object and exposes some specific methods.
Doing this allows you to easily change the type of collection later. Maybe a LinkedHashSet yields better performance? This will be possible because your code is oblivious to the real type of collection and thus cannot call methods that aren’t available in all Collection types.
You might want to read up on the Collections Framework.

Understanding "Coding to an Interface" to hide implementation details [duplicate]

This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 1 year ago.
I'm learning about the "coding to an interface to hide implementation details" design principle, and I'm confused over this idea. In my example, I have a WorkoutRoutine class that has a List of RoutineStep. By following the coding to an interface principle, my getWorkoutRoutine() method will return the List interface so that the implementation details of which list is used is hidden from the client.
What if I decide to change the implementation from a List of RoutineStep to an array of RoutineStep, won't disclosing the return type as List reveal to the client that a list was implemented and not an array, tree, graph, or any other data structure? How can I best encapsulate my data structure for holding a collection of RoutineStep, such that I can change the implementation of the data structure without the client code breaking if the List was changed to an array, tree, graph, etc?
public class WorkoutRoutine {
private List<RoutineStep> workoutRoutine;
public List<RoutineStep> getWorkoutRoutine() {
//What if I later decide to change the data structure from a List to an array, tree,
//graph, set, map. What approach should I take so that the client code doesn't break
//as they would have already coded to receive a List but after changing the
//implementation from a list to an array or any other data structure, their code would
//break.
}
}
The idea is to return a type that is as generic as possible but specific enough.
For example returning a LinkedList may be too specific - if the client starts using the getFirstmethod and you later on decide to return an ArrayList for performance reasons, the client code will break. Hence the principle of returning a more generic type, such as a List.
You could even go more generic and return a Collection - it may make sense if you don't think the client code will need to access the n-th position in the collection for example. But if you feel that accessing the n-th step of the routine (routine.get(n-1)) without having to iterate is an important feature, it means that Collection is too generic for your use case.
decide to change the implementation from a List of RoutineStep to an array of RoutineStep
The ArrayList is just what you would choose – a List implementation backed by an array structure.
Later, you may find that your app is more often inserting elements into the middle of the list rather than appending to the end. So you decide to switch your choice of List implementation from ArrayList to LinkedList. By having your method return an object of the more general interface List rather than the more specific concrete classes of ArrayList and LinkedList, your change from one class to the other does not break calling code.
By the way, we generally do not use array in Java where we expect to need the features and flexibility of a List or Set from the Java Collections Framework. We generally use arrays only where we need to conserve RAM because of deploying to constrained devices or we need maximum performance. Arrays were also used for their more convenient compact literals, but the new List.of and Set.of methods fill that need.
without the client code breaking if the List was changed to an array, tree, graph, etc?
If you are making such a massive change to the data structures of your app, then no amount of encapsulation will mask that change. At some point, your design changes may indeed break existing code.
Such breaking changes may be a natural part of the early stages in an emergent design. This is a normal part of our work. Later, in an evolved design, proper use of encapsulation with help protect against smaller changes having wider impact than is necessary, will make your codebase less brittle.

Assigning ArrayList to List [duplicate]

This question already has an answer here:
What is the difference between List and ArrayList? [duplicate]
(1 answer)
Closed 10 years ago.
Is there any Difference between two lines in the following
ArrayList<String> arrName = new ArrayList<String>();
List<String> arrName = new ArrayList<String>();
Thanks for Reply
Almost always the second one is preferred over the first one. The second has the advantage that the implementation of the List can change (to a LinkedList for example), without affecting the rest of the code. This is will be difficult to do with an ArrayList, not only because you will need to change ArrayList to LinkedList everywhere, but also because you may have used ArrayList specific methods.
Try to hide specific implementation behind an Interface whenever possible. see this
The second approach is usually the preferred one as it hides the implementation behind an interface.
This means that later on, if the requirements will change and will require another implementation of the List interface, you can change just one line of code and everything else will still work because you were coding to an interface not to a class.
There is not much difference per se, but List shall be used whenever possible as it is an interface and you may see in standard libraries' methods parameters are generally List<K>, so that any specific implementation can be passed, like ArrayList or LinkedList.
Second is example of Program to Interface and its the preferred way.
For details What does it mean to "program to an interface"?
The latter is usually recommended as long as you only need a List interface later on. That's called "programming to interface, not implementation".
As for the detailed difference between them, I have answered in another question on stackoverflow: The difference between "C c = new C()" and "A c = new C()" when C is a subclass of A in Java

How to declare an ArrayList? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why should the interface for a Java class be prefered?
I m relatively new to java and i have just started on collections framework.
While on ArrayList I encountered on two ways people declare it. For example to declare an ArrayList of Strings :
List<String> l = new ArrayList<String>();
or
ArrayList<String> al = new ArrayList<String>();
Which one of these two should I use and what is the difference between them?
I know that the actual methods called are decided at runtime and hence the methods called will all be of ArrayList class only but still the first declaration restricts the methods that can be called.
The first way is, I have heard, called "coding to an interface". Any method will be invoked using the variable l and hence only methods provided by List interface can be called, whereas, in the second example we can call all the methods provided not only by List but by the Object class also (like finalize(), wait() etc). So why even in the first place people even use the first declaration??
You should always use least specific interface possible. This makes it easier to substitute alternate implementations if a more appropriate one exists. For example, methods that take List don't care if the list is a linked list or an array list. You can choose whichever one is more appropriate.
I personally recommend using List<String> l = new ArrayList<String>();
The reason is you typically don't need to know you're working with an ArrayList. You just need something that operates like a list. There's a lot of behaviors on ArrayList that people don't need access to. Consider "EnsureCapacity". They don't need that - they just need the List operations. As a general rule, you want to limit the exposure of data and functionality on a "need to know" basis, and users of your list do not need to know (by default) what implementation you used.
Obviously, if they do need to know that you're using an ArrayList instead of a LinkedList, for instance, then you would want to use an ArrayList reference instead of a List reference. For most purposes though, that's not necessary.

List versus ArrayList as reference type?

Ok so I know that Set, List and Map are interfaces but what makes the first line of code any better than the second line?
List myArr = new ArrayList();
ArrayList myArr = new ArrayList();
If you use the first form, you are saying all you are ever going to use is the functionality of the List interface - nothing else, especially nothing extra added by any implementation of it. This means you can easily change the implementation used (e.g. just substitute LinkedList for ArrayList in the instantiation), and not worry about it breaking the rest of the code because you might have used something specific to ArrayList.
A useful general principle about types in programming (sometime referred to as the robustness principle) is as follows:
Be liberal about what you accept
Be conservative about what you emit
List is more liberal than ArrayList, since List can be any kind of List implementation e.g. an ArrayList, a LinkedList or FrancosSpecialList. Hence it is a good idea to be liberal and accept any kind of list since you may want to change the implementation later.
The main reason to use ArrayList explicitly as a type (your second case) is if you need to use methods that are specific to ArrayList that are not available through the List interface. In this case a generic List won't work (unless you want to do lots of ugly and confusing casting), so you might as well be explicit and use an ArrayList directly. This has the added bonus of hinting to a reader that specific features of ArrayList are needed.
As you can see from the source of ArrayList here, most of the methods implemented are annotated as #override because all of them that are defined through List interface so, if you are gonna use just basic functionalities (that is what you are gonna do most of the time) the difference won't be any practical one.
The difference will come if someday you will think that the features of the ArrayList are not suitable anymore for your kind of problem and you will need something different (a LinkedList for example). If you declared everything as List but instantiated as ArrayList you will easily switch to new implementation by changing the instantiations to new LinkedList() while in other case you will have to change also all variable declarations.
Using List list = new ArrayList() is more OOP style since you declare that you don't care about the specific implementation of the list, and that you want to discard the static information about the type since you will rely on the interface provided by this kind of collection abstracting from its implementation.

Categories

Resources